I am creating an extension that will download a mp3 file off a website. I am trying to do this by creating a new tab with the link to the mp3 file, but chrome keeps opening it inside the player instead of downloading it. Is there any way I can create a pop-up to ask the user to "save-as" the file?
-
2see http://stackoverflow.com/questions/399486/open-the-save-image-dialog-using-jquery-javascript – serg Jan 31 '11 at 01:44
5 Answers
Fast-forward 3 years, and now Google Chrome offers chrome.downloads
API (since Chrome 31).
After declaring "downloads"
permission in the manifest, one can initiate a download with this call:
chrome.downloads.download({
url: "http://your.url/to/download",
filename: "suggested/filename/with/relative.path" // Optional
});
If you want to generate the file content in the script, you can use Blob
and URL
APIs, e.g.:
var blob = new Blob(["array of", " parts of ", "text file"], {type: "text/plain"});
var url = URL.createObjectURL(blob);
chrome.downloads.download({
url: url // The object URL can be used as download URL
//...
});
For more options (i.e. Save As dialog, overwriting existing files, etc.), see the documentation.
-
Thanks! Is it possible to have Chrome append a file to an existing file? I want to do download a file made of fragments, resulting in one complete file instead of multiple fragtments. – marlar Jun 13 '14 at 17:13
-
1@marlar For that, it would be best to employ the [filesystem API](http://www.html5rocks.com/en/tutorials/file/filesystem/) (despite the warning, it's supported in Chrome) to get the chunks, build the complete file, and then `download` the result into the Downloads folder. But it's a different question; if you still need help, ask a new question. – Xan Jun 13 '14 at 17:17
-
4
-
1@Xan i got this error : `Unchecked runtime.lastError while running downloads.download: Invalid filename` any idea ? – questionasker Jul 02 '17 at 03:02
-
-
4@anunixercoder probably already found the issue, but for whomever cames after: this code needs to be on `background.js`, it doesn't run on `content.js` – brasofilo Dec 17 '18 at 16:13
-
-
-
Is it at all possible to download the file using an external download manager like IDM. By default in chrome when I download the file it downloads using IDM but in this case, when downloading using the API it always downloads with the default chrome downloader. – Rishav Nov 09 '19 at 09:07
-
-
I use ```chrome.downloads.download``` and I want to catch if the response status is 400, how can I do it? – yusuf_sabri Feb 21 '21 at 13:09
I used a variation on the solution here
var downloadCSS = function () {
window.URL = window.webkitURL || window.URL;
file = new BlobBuilder(); //we used to need to check for 'WebKitBlobBuilder' here - but no need anymore
file.append(someTextVar); //populate the file with whatever text it is that you want
var a = document.createElement('a');
a.href = window.URL.createObjectURL(file.getBlob('text/plain'));
a.download = 'combined.css'; // set the file name
a.style.display = 'none';
document.body.appendChild(a);
a.click(); //this is probably the key - simulatating a click on a download link
delete a;// we don't need this anymore
}
One thing you need to bare in mind is that this code needs to execute on the page and not your extension - otherwise the user won't see the download action that chrome does. The download will still happen and you will be able to see it in the download tab, but they won't see the actual download happen.
Edit (afterthought about making your code execute on the content page):
The way you make an action occur on the content page rather than your extension is to use Chrome "message passing". Basically, you pass a message from your extension (which is almost like a separate page) to the content page that the extension is working with. You then have a listener that your extension has injected into the content page that reacts to the message and does the download. Something like this:
chrome.extension.onMessage.addListener(
function (request, sender, sendResponse) {
if (request.greeting == "hello") {
try{
downloadCSS();
}
catch (err) {
alert("Error: "+err.message);
}
}
});
-
`delete a;` doesn't do what you think it does here, you actually need `a.parentNode.removeChild(a);`. (Deleting the reference to a is not necessary because as a local variable its lost when the function completes). – ejm Nov 19 '17 at 01:24
-
Do you if this still works?, `chrome.downloads` doesn't work the way I'd like it to. – olfek Mar 24 '18 at 21:20
-
Still works, but hit the same problem I was having with chrome downloads. Chrome is _not_ ok with allowing extensions to download multiple files. – olfek Mar 26 '18 at 00:19
This is a slightly modified version of @Steve Mc's answer that just makes it into a generalized function that can easily be copied and used as is:
function exportInputs() {
downloadFileFromText('inputs.ini','dummy content!!')
}
function downloadFileFromText(filename, content) {
var a = document.createElement('a');
var blob = new Blob([ content ], {type : "text/plain;charset=UTF-8"});
a.href = window.URL.createObjectURL(blob);
a.download = filename;
a.style.display = 'none';
document.body.appendChild(a);
a.click(); //this is probably the key - simulating a click on a download link
delete a;// we don't need this anymore
}

- 4,659
- 1
- 34
- 49
-
1For current people: SteveMC's answer no longer works, but this one does. – Ian Hyzy Jul 07 '17 at 17:56
Here's a concise way to download a file using "downloads" permission in Chrome manifest using @Xan and @AmanicA's solution
function downloadFile(options) {
if(!options.url) {
var blob = new Blob([ options.content ], {type : "text/plain;charset=UTF-8"});
options.url = window.URL.createObjectURL(blob);
}
chrome.downloads.download({
url: options.url,
filename: options.filename
})
}
// Download file with custom content
downloadFile({
filename: "foo.txt",
content: "bar"
});
// Download file from external host
downloadFile({
filename: "foo.txt",
url: "http://your.url/to/download"
});

- 4,086
- 10
- 30
- 46
-
The concision is much appreciated, wish I'd noticed it sooner. There's no need to simulate a click on a hidden `a` tag. Thanks! – SimplGy Nov 11 '18 at 05:52
-
Is this script in the content script or background script or somewhere else? I am getting a "Uncaught TypeError: Cannot read property 'download' of undefined" on the line "chrome.downloads.download({ – Craig Lambie Jan 28 '20 at 18:39
I did it as follows in Appmator code on Github.
The basic approach is to build your Blob, however you want (Chrome has a responseBlob on XmlHttpRequest so you can use that), create an iframe (hidden, display:none
) then assign the src of the iframe to be the Blob.
This will initiate a download and save it to the filesystem. The only problem is, you can't set the filename yet.
var bb = new (window.BlobBuilder || window.WebKitBlobBuilder)();
var output = Builder.output({"binary":true});
var ui8a = new Uint8Array(output.length);
for(var i = 0; i< output.length; i++) {
ui8a[i] = output.charCodeAt(i);
}
bb.append(ui8a.buffer);
var blob = bb.getBlob("application/octet-stream");
var saveas = document.createElement("iframe");
saveas.style.display = "none";
if(!!window.createObjectURL == false) {
saveas.src = window.webkitURL.createObjectURL(blob);
}
else {
saveas.src = window.createObjectURL(blob);
}
document.body.appendChild(saveas);
An example of using XmlHttpRequest's responseBlob (see: http://www.w3.org/TR/XMLHttpRequest2/#dom-xmlhttprequest-responseblob)
var xhr = new XmlHttpRequest();
xhr.overrideMimeType("application/octet-stream"); // Or what ever mimeType you want.
xhr.onreadystatechanged = function() {
if(xhr.readyState == 4 && xhr.status == 200) {
var blob = xhr.responseBlob();
var saveas = document.createElement("iframe");
saveas.style.display = "none";
if(!!window.createObjectURL == false) {
saveas.src = window.webkitURL.createObjectURL(blob);
}
else {
saveas.src = window.createObjectURL(blob);
}
document.body.appendChild(saveas);
}

- 16,315
- 5
- 56
- 88
-
-
-
Yah, Can you edit the code to show how to do that? I have no idea where to put the location. – Franz Payer May 21 '11 at 21:15
-
How can you set it to download as the correct file type? Chrome keeps trying to download it as an html file. The page that the blob is created on also freezes up and crashes. It also appears that the source of the blob is blank. – Franz Payer May 29 '11 at 00:13
-
Can you show some example code of what you are trying to do that makes it crash - it is so hard to tell what you are now trying to do. I would say that I have added a small piece of code to override the mimetype. – Kinlan May 29 '11 at 16:18
-
http://stackoverflow.com/questions/6165266/downloading-mp3-files-using-html5-blobs-in-a-chrome-extension – Franz Payer May 29 '11 at 16:41