Unable to download file using chrome.downloads.download API

2,827 views
Skip to first unread message

Activity Recorder

unread,
Mar 10, 2023, 7:13:01 AM3/10/23
to Chromium Extensions
We are under the process of migrating our extension to MV3. For this trying to download the file using chrome.downloads.download API which will be called from service worker using chrome.scripting.executeScript API.

We tried to create url using URL.createObjectURL which is not supported in MV3 with blob content.

File is not getting downloaded and no error in console or errors page.
API call in service worker:
chrome.action.onClicked.addListener(async () => {
  let tab = await getCurrentTab();

  chrome.scripting.executeScript({
    target: {tabId: tab.id},
    files: ['jszip.min.js','content-script.js']
  });
});
API call in content-script.js:
    var zip = new JSZip();
    zip.folder("folder_1").file('sequenceName.txt', "Hello World\n").generateAsync({
type: "blob"
}).then(function (content) {
chrome.downloads.download({
url: 'content:application/zip,' + content,
filename: 'sequenceZip.zip',
saveAs: true
});
});

Please advice a solution. 
Thanks in advance.

Oliver Dunk

unread,
Mar 10, 2023, 7:25:21 AM3/10/23
to Activity Recorder, Chromium Extensions
Hi,

Could you try a data URI, such as something starting data:application/zip;base64?

I'm not familiar with content URIs. It's possible there's a way to get those working too but I'm honestly not sure!

As a fallback, you could also use Offscreen Documents (https://developer.chrome.com/blog/Offscreen-Documents-in-Manifest-v3/) which support a "BLOBS" reason for calling createObjectURL.
Oliver Dunk | DevRel, Chrome Extensions | https://developer.chrome.com/ | London, GB


--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/chromium-extensions/189b0871-f9ff-4a96-8899-2641866f8938n%40chromium.org.

Activity Recorder

unread,
Mar 10, 2023, 7:43:57 AM3/10/23
to Chromium Extensions, Oliver Dunk, Chromium Extensions, Activity Recorder
Thanks Oliver. 
File download is not happening with data URI also.
Will try offscreen Documents.

Oliver Dunk

unread,
Mar 10, 2023, 8:32:12 AM3/10/23
to Activity Recorder, Chromium Extensions
Hmm, it worked on my end.

Can you try the following?

```
chrome.downloads.download({
    url: 'data:application/zip;base64,A',
    filename: 'example.zip',
    saveAs: true
});
```

Of course it's fake data but should at least show the download prompt.

Offscreen documents are fine, but are more work for the browser, so nice to avoid when possible :)

Oliver Dunk | DevRel, Chrome Extensions | https://developer.chrome.com/ | London, GB
Message has been deleted
Message has been deleted

Activity Recorder

unread,
Mar 13, 2023, 1:03:40 AM3/13/23
to Chromium Extensions, Oliver Dunk, Chromium Extensions, Activity Recorder
Thanks Oliver.
Updated in the same way, download prompt is not getting displayed. 
manifest.json is as follows. Am I missing any permissions?
{
  "name": "MV3 Migration - my test extension for save using downloads API",
  "version": "0.1",
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  },
  "permissions": [
    "scripting",
    "activeTab",
"downloads"
  ],
  "action": {}
}

Not able to attach entire extension zip, so pasting the content here.

Oliver Dunk

unread,
Mar 13, 2023, 2:57:23 PM3/13/23
to Activity Recorder, Chromium Extensions
Hmm, that looks fine to me. I just built an extension using your manifest.json and the following code in the service worker:

```
chrome.runtime.onInstalled.addListener((details) => {

  chrome.downloads.download({
    url: 'data:application/zip;base64,A',
    filename: 'example.zip',
    saveAs: true
  });
});
```

It fails to download (I assume because the data is invalid) but I do get a prompt.

Does that work for you? If not, I'd be curious to see either your code (you could put it on GitHub if you're comfortable) or a video showing what you're trying.

Thanks!

Oliver Dunk | DevRel, Chrome Extensions | https://developer.chrome.com/ | London, GB

Activity Recorder

unread,
Mar 14, 2023, 8:34:07 AM3/14/23
to Chromium Extensions, Oliver Dunk, Chromium Extensions, Activity Recorder
Thanks Oliver.
Download prompt is opening if I use like above in service worker.

My scenario is  different. I'm using the download API in the file which is called using chrome.scripting.executeScript API. Like below,

service worker:
async function getCurrentTab() {
  let queryOptions = { active: true, currentWindow: true };
  let [tab] = await chrome.tabs.query(queryOptions);
  return tab;

}

chrome.action.onClicked.addListener(async () => {
  let tab = await getCurrentTab();

  chrome.scripting.executeScript({
    target: {tabId: tab.id},
    files: ['jszip.min.js','content-script.js']
  });
});

content-script.js:
var zip = new JSZip();
    zip.folder("folder_1").file('sequenceName.txt', "Hello World\n").generateAsync({
type: "blob"
}).then(function (content) {
chrome.downloads.download({
url: 'data:application/zip;base64,A',
filename: 'sequenceZip.zip',
saveAs: true
});
});
manifest.json:
As mentioned above.

Simeon Vincent

unread,
Mar 14, 2023, 5:15:19 PM3/14/23
to Chromium Extensions, app.s...@gmail.com, olive...@google.com, Chromium Extensions
The Download API isn't exposed in content scripts. To test this I revised the demo provided in the last post.

manifest.json
{
"name": "Downloads API in Content Scripts (test)",
"version": "1.0",
"manifest_version": 3,
"action": {},
"permissions": [
"downloads",
"scripting",
"activeTab"
],
"background": {
"service_worker": "background.js"
}
}

background.js
chrome.action.onClicked.addListener((tab) =>
chrome.scripting.executeScript({
target: {tabId: tab.id},
files: ['content.js']
}));

content.js
chrome.downloads.download({
url: 'data:application/zip;base64,A',
filename: 'sequenceZip.zip',
saveAs: true
});

When you click the extension's button in the toolbar, the following message will be logged to the console:

Uncaught TypeError: Cannot read properties of undefined (reading 'download') at content.js:1:18


Simeon - @dotproto

Activity Recorder

unread,
Mar 15, 2023, 7:50:04 AM3/15/23
to Chromium Extensions, Simeon Vincent, app.s...@gmail.com, olive...@google.com, Chromium Extensions
Thanks Simeon.

I hope download API is wrongly used in content.js. Using the same way in background.js also gives the same error.

Our requirement is to download a zip created using JSZip with the help of download API.

We were able to download zip using JSZip and file saver in the content-script.js file,
var zip = new JSZip();
zip.file("Hello.txt", "Hello World\n");
var img = zip.folder("images");
zip.generateAsync({type:"blob"})
.then(function(content) {
saveAs(content, "example.zip");
});

The same cannot be achieved with JsZip and download API.

Simeon Vincent

unread,
Mar 15, 2023, 5:57:04 PM3/15/23
to Activity Recorder, Chromium Extensions, olive...@google.com
What do you mean by "Using the same way in background.js also gives the same error"? Did the extension I provided throw an error? If so, what error did you see? If you encountered an error using different extension code, please provide the code where you're seeing the error in order to help debug the issue.

We were able to download zip using JSZip and file saver in the content-script.js file,

I'm also not sure what you mean by "file saver." What interface were you using before?

Simeon - @dotproto

Activity Recorder

unread,
Mar 16, 2023, 8:51:34 AM3/16/23
to Chromium Extensions, Simeon Vincent, Chromium Extensions, olive...@google.com, Activity Recorder
filesaver is a javascript library to download files using javascript. Ref: https://github.com/eligrey/FileSaver.js/

Our aim is to download blob content from content script which can be achieved in MV3 using JsZip and FileSaver. We want to download blob using Jszip and chrome downloads API.
Let us know if there is another way to download zip(zip created with a file that contains user action data like page visited and request and response etc.) file in chrome extensions.

Activity Recorder

unread,
Mar 31, 2023, 6:05:10 AM3/31/23
to Chromium Extensions, Activity Recorder, Simeon Vincent, Chromium Extensions, olive...@google.com
Able to download a text file using a sample extension below,

background.js:
chrome.action.onClicked.addListener(async () => {
var data = {"test" : "test2"};
chrome.downloads.download({
url: 'data:text/plain;base64,' + btoa(JSON.stringify(data)),
filename: 'fileName.txt',
saveAs: true
})
}); 
manifest.js:
{
  "name": "MV3 - Basic data text File download",

  "version": "0.1",
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  },
  "permissions": [
    " downloads",
    "activeTab"
  ],
  "action": {}
}

This downloads a file called "fileName.txt" with content {"test" : "test2"} in it.

Now our next goal is to download a zip file with the above generate text file. Downloaded "sample.zip" should contain "fileName.txt" with content {"test" : "test2"} in text file.

Activity Recorder

unread,
Apr 12, 2023, 2:56:22 AM4/12/23
to Chromium Extensions, Activity Recorder, Simeon Vincent, Chromium Extensions, olive...@google.com
Tried to find a way to download the file into a zip format but unable to find a solution. 
Please assist if there is way to download zip files in the chrome extension.
Thanks in advance.

Patrick Kettner

unread,
Apr 12, 2023, 12:15:18 PM4/12/23
to Activity Recorder, Chromium Extensions, Simeon Vincent, olive...@google.com
Do you need to use chrome.downloads? If you are generating a blob, can you use standard web apis to append an achor tag to the page, generate a blob url as the href, and then programmatically click the anchor?

--
You received this message because you are subscribed to the Google Groups "Chromium Extensions" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-extens...@chromium.org.

Activity Recorder

unread,
Apr 14, 2023, 1:47:50 AM4/14/23
to Chromium Extensions, Patrick Kettner, Chromium Extensions, Simeon Vincent, olive...@google.com, Activity Recorder
Thanks Patrick.
To generate a blob URL need to use "URL.createObjectURL()".

As per URL.createObjectURL() - Web APIs MDN (mozilla.org) article, "URL.createObjectURL()" feature is not available in Service Workers due to its potential to create memory leaks.

Do we have an alternate way to generate blob URL in service workers?

Thanks in advance. 


Patrick Kettner

unread,
Apr 14, 2023, 1:56:20 AM4/14/23
to Activity Recorder, Chromium Extensions, Simeon Vincent, olive...@google.com
You may be able to do this in an offscreenDocument, but I am not sure if that would properly trigger. I can look into it tomorrow afternoon

Patrick Kettner

unread,
Apr 14, 2023, 11:56:47 AM4/14/23
to Activity Recorder, Chromium Extensions, Simeon Vincent, olive...@google.com
Apologizes, I had missed the earlier part of the thread. 

Can you share a zip of the code that is breaking? I would be happy to look into it.

Activity Recorder

unread,
Apr 20, 2023, 6:07:34 AM4/20/23
to Chromium Extensions, Patrick Kettner, Chromium Extensions, Simeon Vincent, olive...@google.com, Activity Recorder
Unable to upload zip files here. code goes here,

background.js:
chrome.action.onClicked.addListener(async () => {
  let tab = await getCurrentTab();

  chrome.scripting.executeScript({
    target: {tabId: tab.id},
    files: ['jszip.min.js','content-script.js']
  });
});

content-script.js:
    var zip = new JSZip();
    zip.folder("folder_1").file('sequenceName.txt', "Hello World\n").generateAsync({
type: "blob"
}).then(function (content) {
chrome.downloads.download({
url: 'content:application/zip,' + content,

filename: 'sequenceZip.zip',
saveAs: true
});
});

manifest.json:
{
  "name": "MV3 Migration - my test extension for save",

  "version": "0.1",
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  },
  "permissions": [
    "scripting",
    "activeTab",
"downloads"
  ],
  "action": {}
}

jszip.min.js: PFA, jszip.txt


jszip.txt
Reply all
Reply to author
Forward
0 new messages