I've been researching and i did not found anything about that.
I need a chrome application that will run on Chrome OS be able to download a file (image, mp3, video, etc) and then display the content as HTML.
I mean if the app download a video, then play it on a video tag. The same for a image...download it and display on img tag.
Thanks!!
I also worked with this issue, here a working example of saving to filesystem + showing on screen:
var video = document.getElementById("video");
fetch('http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_20mb.mp4')
.then(function(response) {
return response.blob();
})
.then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
video.src = objectURL;
var config = {type: 'saveFile', suggestedName: chosenEntry.name};
chrome.fileSystem.chooseEntry(config, function(writableEntry) {
writeFileEntry(writableEntry, myBlob, function(e) {
output.textContent = 'Write complete :)';
});
});
})
See Chrome App documentation on Handling external content. It provides a good overview.
A short version:
Declare the origins you're going to access in the manifest.
Fetch the resource via XHR (or, indeed, Fetch API).
Use the response as a blob: (you can plug it into a <video src="...">, for instance).
Optionally, save the resource locally.
Related
In any browser, if you saw an image, you can right-click on it and click "save as" to download it.
I'm trying to make a button to download an image
The download button should download the image above, the barcode.
I am using react, not sure if this has something to do with the answers.
I read that you can use the <a/> tag with the download attribute, however, I'm on Firefox, and it's redirecting me to a page where the barcode image is hosted, and it's not opening the download window instead:
The code is pretty simple, it look as follows:
<a href='https://barcode.tec-it.com/barcode.ashx?data=${product.barcode}&code=&multiplebarcodes=true&backcolor=%23ffffff&quietzone=10&quietunit=Px&size=Small' download>click me</a>
From the MDN docs:
download only works for same-origin URLs, or the blob: and data:
schemes.
I want to implement this, how can I do it?
I'm not the owner of the server where the image is hosted.
Can we do that in 2023?
The other questions are mixing between local images and images hosted on other servers.
So I thought I could create this thread for people interested only in images on third party servers. - so we are all front-end here, no back-end related stuff.
I think your question refers to this old question.
You need something on the server to send a Content-Disposition header to set the file as an attachment so the browser will not try to handle the file internally.
Please see:
href image link download on click
It only works on the same website, not an external link. Try an image of the same website. Ex: <a href="images/detailed-product.png" download>click</a>
You'll need to proxy the request to avoid CORS issues. As the article states it's better to deploy your own proxy, but you can test with a free one, eg: https://codetabs.com/cors-proxy/cors-proxy.html
StackBlitz updated example:
const downloadButton = document.querySelector('button');
downloadButton.onclick = () => {
console.log('download button clicked');
downloadImage(
'https://api.codetabs.com/v1/proxy?quest=https://barcode.tec-it.com/barcode.ashx?data=${product.barcode}&code=&multiplebarcodes=true&backcolor=%23ffffff&quietzone=10&quietunit=Px&size=Small'
);
};
async function downloadImage(imageSrc) {
try {
const image = await fetch(imageSrc);
const imageBlob = await image.blob();
const imageURL = URL.createObjectURL(imageBlob);
const link = document.createElement('a');
link.href = imageURL;
link.download = 'image.jpg';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} catch (error) {
console.log(error);
}
}
<button>Download image</button>
To do that, you can utilize the createObjectURL static method from URL to create download link for the image. Then, we create temporary <a> in a variable to open that link programmatically.
async function downloadImage(imageSrc) {
const image = await fetch(imageSrc)
const imageBlob = await image.blob()
const imageURL = URL.createObjectURL(imageBlob)
const link = document.createElement('a')
link.href = imageURL
link.download = 'myimage.jpg'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
I'm embedding PDFs from a base64 string like this:
var pdfData = 'data:application/pdf;filename=MY_CUSTOM_FILENAME.pdf;base64,' +
'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' +
'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' +
'TWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0K' +
'Pj4KZW5kb2JqCgozIDAgb2JqCjw8CiAgL1R5cGUgL1BhZ2UKICAvUGFyZW50IDIgMCBSCiAg' +
'L1Jlc291cmNlcyA8PAogICAgL0ZvbnQgPDwKICAgICAgL0YxIDQgMCBSIAogICAgPj4KICA+' +
'PgogIC9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKCjQgMCBvYmoKPDwKICAvVHlwZSAvRm9u' +
'dAogIC9TdWJ0eXBlIC9UeXBlMQogIC9CYXNlRm9udCAvVGltZXMtUm9tYW4KPj4KZW5kb2Jq' +
'Cgo1IDAgb2JqICAlIHBhZ2UgY29udGVudAo8PAogIC9MZW5ndGggNDQKPj4Kc3RyZWFtCkJU' +
'CjcwIDUwIFRECi9GMSAxMiBUZgooSGVsbG8sIHdvcmxkISkgVGoKRVQKZW5kc3RyZWFtCmVu' +
'ZG9iagoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDEwIDAwMDAwIG4g' +
'CjAwMDAwMDAwNzkgMDAwMDAgbiAKMDAwMDAwMDE3MyAwMDAwMCBuIAowMDAwMDAwMzAxIDAw' +
'MDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9v' +
'dCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G';
function loadPdf() {
var pdf= document.querySelector('.pdf')
var pobj = document.createElement('object')
pobj.className= "pdf_object"
pobj.setAttribute('data', pdfData)
pobj.setAttribute('type', 'application/pdf')
pdf.appendChild(pobj)
}
.pdf_object {
width: 100%;
height: 700px;
}
<div>
<button onclick="loadPdf();">
CLICK TO LOAD BELOW THE PDF
</button>
</div>
<div class="pdf"></div>
This works both on Firefox and Chrome.
My problem is I cannot customize the filename for the pdf download actions. Notice that I'm using the filenameparameter ('data:application/pdf;filename=MY_CUSTOM_FILENAME.pdf;...), but it's ignored.
On Firefox, I get this warning (related code is here):
"getPDFFileNameFromURL: ignoring "data:" URL for performance reasons."
And the pdf's filename is the default document.pdf.
On Chrome, I get no warning, but filename sticks to the default download.pdf.
So, how can I customize the filename? Is that possible?
I tried these ways, unsuccessfully:
Checked PDFObject, which is a library doing basically what I'm doing in this post (discovered it while writing this!), but they seem to not allow any customization on the filename.
I tried to load pdf on an <iframe>, and then manipulating its content. But I get (at least in Firefox) a Cross Origin error
It seems that Mozilla's PDF viewer (PDF.js) also checks the Content-Disposition header for guessing out the pdf's filename. Could be possible to somehow simulate an HTTP request (always locally in the browser, as I work with base64 strings) and use it to load the pdf viewer?
I know the solution can be to directly use PDF.js, but if possible I would love to avoid this dependency (and also the coding, cause it's not so straightforward to implement it). At the end, I just want to customize filename!
Thanks!
EDIT: The code snippet below does not work on Chrome (Failed to load 'data:application/pdf;filename=MY_CUSTOM_FILENAME.pdf;base64,....' as a plugin, because the frame into which the plugin is loading is sandboxed.), but it works if you open a plan .html file.
EDIT 2: I found a solution but it just works on Firefox.
We will convert our base64 string to a Blob as explained here, convert this Blob to Url and add a filename parameter to this url (using '#' as explained here).
So, the loadPdf() function is this:
function loadPdf() {
fetch(pdfData)
.then(res => res.blob())
.then(blob => {
try {
var blobUrl = URL.createObjectURL(blob)
// This line makes Chrome crash, we have to remove it there
// But it works on Firefox
blobUrl+= '#filename=MY_CUSTOM_FILENAME.pdf'
var pdf= document.querySelector('.pdf')
var pobj = document.createElement('object')
pobj.className= "pdf_object"
pobj.setAttribute('data', blobUrl)
pobj.setAttribute('type', 'application/pdf')
pdf.appendChild(pobj)
} catch(e) {
console.error(e)
}
})
}
When downloading from Firefox's Pdf viewer, we'll successfully see MY_CUSTOM_FILENAME.pdf.
But on Chrome we will see the Blob url's hash. And:
it seems impossible to change that hash
even if I use an <iframe> (instead of an <object>) to load my inline pdf, Chrome will make use of an <embed>. So, there's no way to "hack" it.
Any other tip from this perspective?
I am using Chrome 79.
I am trying to start download of an image within a html page. The image is located on the same server as the webpage, but it is served via nginx server via different port. This apparently gets me to cross-origin security problems.
First I tried to use the standard
var a = document.createElement('a');
a.download = "file.bmp";
a.href = "http://xxxxxxx/xxx/somefile.bmp";
document.body.appendChild(a);
a.click();
a.remove();
Interestingly this gets me to the behaviour that my image is displayed in a new tab, but not downloaded. I assume this is due to cors reasons?
After reading discussion on this topic in :
Chrome 65 blocks cross-origin <a download>. Client-side workaround to force download?
I tried to use the approach presented there using the fetch function. Unfortunatelly this does not solve my problem. I get a response with "opaque" type and my blob is undefined...
var url = "http://xxxxxxxxx/xxx/somefile.bmp";
fetch(url, {
mode: 'no-cors'})
.then(function(response){handleBlob(response);})
.catch(e => console.error(e));
-------
function handleBlob(response)
{
var blob = response.blob;
var blobUrl = URL.createObjectURL(blob);
var ImageTest = document.getElementById("DummyLink");
ImageTest.download = "file.bmp";
ImageTest.href = blobUrl;
ImageTest.click();
}
I thought this is all very strange - the server name of the resource is same as of the webpage, so I would assume there is no real security danger here...
Any suggestions or workarounds on how to trigger a download of an image to the disk would be greatly appreciated.
Not 100% sure what your trying to do.
var url = 'http://webpage.com/images/images.jpg',
var img = document.createElement('img');
img.src = src;
document.getElementById("DummyLink").appendChild(img);
In my web application I have supported user to upload any type of document (.png, .jpg, .docx, .xls, ... ) I'm trying to implement download functionality for these documents.
In Google Chrome if you click on Download link Save dialog is shown for all above documents.
In Mozilla Firefox for docx and xls works fine, Save dialog is shown but for .png and .jpg download tag is not working as expected i.e., download dialog or Save dialog does not appear, it directly open that image.
My code:
Download
I have tried almost all solutions mentioned on stackoverflow and suggested by Google. But most of them says that 'check firefox version' and other changes like:
try adding the element to the DOM before triggering the click
Remove filename from download tag it is of boolean type and etc.
I have also tried w3schools lesson on anchor tag and download attribute but nothing seems to be working.
My Mozilla Firefox version is: 38.0.5
P.S.: in chrome as well as in firefox .docs, .xls, .pdf documents work fine, problem is for .png and .jpg in firefox.
Firefox will handle png and jpeg using default handling, which is to inline them in the document. When clicking a link, even if download attribute is defined, seem to make Firefox think it has a new image ignoring the download aspect of it. This may be a temporary bug.
Here is a way, admittedly not super-elegant, to get around this problem forcing the image to be interpreted as an octet-stream.
It does not work inline on Stackoverflow so you have to test it on jsFiddle.
The code does the following:
Scans the document for a-tags.
Those which has data-link set will have a common click-handler attached.
When clicked the link is extracted from the data-link attribute (href is se to #), loaded as an ArrayBuffer via XHR (CORS requirements applies, not a problem in this case), and is converted to an Object-URL with the Blob set to mime-type octet/stream
The Object URL is set as window.location to redirect to this binary data which will make the browser ask user to download the file instead.
var links = document.querySelectorAll("a"), i = 0, lnk;
while(lnk = links[i++]) {
if (lnk.dataset.link.length) lnk.onclick = toBlob;
}
function toBlob(e) {
e.preventDefault();
var lnk = this, xhr = new XMLHttpRequest();
xhr.open("GET", lnk.dataset.link);
xhr.responseType = "blob";
xhr.overrideMimeType("octet/stream");
xhr.onload = function() {
if (xhr.status === 200) {
window.location = (URL || webkitURL).createObjectURL(xhr.response);
}
};
xhr.send();
}
Example tag:
Click to download
The drawback is that you'll loose the extension in the filename.
This is also possible to do using a Data-URL, but a data-url has a 166% overhead compared to using ArrayBuffer and a blob.
I had a similar problem with firefox not handling the download attribute, even for same-domain files.
My target files are actually hosted on AWS, so they are cross-domain. I got around this with a same-domain endpoint that downloads the remote file and pipes it to the client.
const express = require('express')
const {createWriteStream} = require('fs')
const downloadVideo = (url) => { return new Promise((resolve, reject) => {
const filePath = `/tmp/neat.mp4`
const ws = createWriteStream(filePath)
request(url, {}, (error, response, body) => {
if(error) { return reject(error) }
resolve(filePath)
}).pipe(ws)
})}
app.get('/api/download', async (req, res) => {
const videoPath = await downloadVideo(req.query.url)
res.sendFile(videoPath)
})
On the client, I send the file path to the download endpoint to get a blob back, which is then converted to an object url. From there, it's standard download attribute stuff.
async download(remoteFilePath){
const a = document.createElement('a')
const dlURL = `/api/download?url=${encodeURIComponent(remoteFilePath)}`
const blob = await fetch(dlURL).then(res => res.blob())
a.href = URL.createObjectURL(blob)
a.setAttribute('download', 'cool.mp4')
document.body.appendChild(a)
a.click()
a.remove()
}
As you are using HTML5 attribute, each browser handling differently. So use https://github.com/dcneiner/Downloadify for client side forceful download instead of viewing in browser.
I'm developing a Chrome extension that will save files to the downloads folder (that's not all it's doing, but that's the part I have trouble with). Right now I'm focusing on PDF files. Basically, when a PDF is opened in Chrome, the user can manually save it using Menu -> Save File As ..., I'm just trying to automate this functionality using the extension, but I haven't found a good way to do it.
Let's say I can detect if the current tab has a PDF file in it (based on answers from this question).
The best thing I have figured out so far is to initiate a download:
chrome.downloads.download({
url: tabs[0].url, saveAs: false,
filename: "my file", /* This will be some unique autogenerated identifier */
conflictAction: "overwrite"
});
This works but has 2 drawbacks:
The file has to be re-downloaded, which is a pain if it's large. Besides, the file has been downloaded already so I should be able to use it.
For some reason this doesn't work with files opened locally ("file://..."). It throws a NETWORK_INVALID_REQUEST and doesn't download.
Is there a better way to save the file?
Note, chromium / chrome browsers appear to append embed element to document.body to display .pdf files
a) detecting pdf utilizing window.location.href , document.querySelectorAll("embed")[0].type;
b) utilizing XMLHttpRequest to request existing document, which should return pdf document as blob response, from cache; see console -> Network -> Headers -> Status Code
To allow opening file: protocol at chromium / chrome browsers, try utilizing command line flag --allow-access-from-files; see How do I make the Google Chrome flag “--allow-file-access-from-files” permanent?
At .pdf document , i.e.g; Ecma-262.pdf try
// check if `document` is `pdf`
if (/pdf/i.test(window.location.href.slice(-3))
|| document.querySelectorAll("embed")[0].type === "application/pdf") {
var xhr = new XMLHttpRequest();
// load `document` from `cache`
xhr.open("GET", "", true);
xhr.responseType = "blob";
xhr.onload = function (e) {
if (this.status === 200) {
// `blob` response
console.log(this.response);
var file = window.URL.createObjectURL(this.response);
var a = document.createElement("a");
a.href = file;
a.download = this.response.name
|| document.querySelectorAll("embed")[0].src
.split("/").pop();
document.body.appendChild(a);
a.click();
// remove `a` following `Save As` dialog,
// `window` regains `focus`
window.onfocus = function () {
Array.prototype.forEach.call(document.querySelectorAll("a")
, function (el) {
document.body.removeChild(el)
})
}
};
};
xhr.send();
};
Addressing only the file:// aspect of your problem. Does your extension have permission to access file://. In order to have access your extension both needs to ask for file:/// and user has to manually grant this access from the extensions page. You can check if you have the requisite permission using https://developer.chrome.com/extensions/extension#method-isAllowedFileSchemeAccess.
See Adding file://. permission to chrome extension for more information about accessing file:// urls. You may also find How can I enable my chrome extension in incognito mode? helpful.
For a related discussion (although not specific for your use case since you already have a PDF file), also see https://code.google.com/p/chromium/issues/detail?id=169337.