使 Chrome 扩展程序下载文件

IT技术 javascript html google-chrome google-chrome-extension
2021-01-28 05:27:37

我正在创建一个扩展程序,它将从网站上下载 mp3 文件。我试图通过创建一个带有 mp3 文件链接的新选项卡来做到这一点,但 chrome 一直在播放器中打开它,而不是下载它。有什么办法可以创建一个弹出窗口来要求用户“另存为”文件?

5个回答

快进 3 年,现在 Google Chrome 提供chrome.downloadsAPI(自 Chrome 31 起)。

"downloads"清单中声明权限,可以通过以下调用启动下载:

chrome.downloads.download({
  url: "http://your.url/to/download",
  filename: "suggested/filename/with/relative.path" // Optional
});

如果要在脚本中生成文件内容,可以使用BlobURLAPI,例如:

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
  //...
});

有关更多选项(即另存为对话框、覆盖现有文件等),请参阅文档

@anunixercoder 可能已经发现了这个问题,但无论是谁来的:这段代码需要打开background.js,它不会运行content.js
2021-03-22 05:27:37
@Xan 我收到这个错误:Unchecked runtime.lastError while running downloads.download: Invalid filename知道吗?
2021-03-24 05:27:37
谢谢!是否可以让 Chrome 将文件附加到现有文件?我想下载一个由片段组成的文件,从而生成一个完整的文件而不是多个片段。
2021-04-03 05:27:37
@marlar 为此,最好使用文件系统 API(尽管有警告,但 Chrome 支持)来获取块,构建完整文件,然后download将结果放入下载文件夹。但这是一个不同的问题。如果您仍然需要帮助,请提出一个新问题。
2021-04-09 05:27:37
“文件名”在我的系统上完全被忽略了!
2021-04-11 05:27:37

我在这里使用了解决方案的变体

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
}

您需要牢记的一件事是,此代码需要在页面上执行而不是在您的扩展程序上执行 - 否则用户将看不到 chrome 执行的下载操作。下载仍然会发生,您将能够在下载选项卡中看到它,但他们不会看到实际的下载发生。

编辑(事后考虑让您的代码在内容页面上执行):

在内容页面而不是扩展程序上执行操作的方式是使用 Chrome “消息传递”基本上,您将消息从扩展程序(几乎就像一个单独的页面)传递到扩展程序正在使用的内容页面。然后,您有一个侦听器,您的扩展程序已将其注入内容页面,该页面对消息做出react并进行下载。像这样的东西:

chrome.extension.onMessage.addListener(
  function (request, sender, sendResponse) {  
      if (request.greeting == "hello") {
          try{
              downloadCSS();
          }
          catch (err) {
              alert("Error: "+err.message);
          }
      }
  });
delete a;不会做你认为它在这里做的事情,你实际上需要a.parentNode.removeChild(a);. (删除对 a 的引用不是必需的,因为作为局部变量它在函数完成时丢失了)。
2021-03-18 05:27:37
仍然有效,但遇到了与 Chrome 下载相同的问题。Chrome是正常与允许扩展下载多个文件。
2021-03-23 05:27:37
你如果这仍然有效吗?,chrome.downloads不像我想要的那样工作。
2021-03-30 05:27:37

这是@Steve Mc's answer的一个稍微修改的版本,只是使它成为一个可以轻松复制和按原样使用的通用函数:

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
}
对于现在的人:SteveMC 的答案不再有效,但这个答案有效。
2021-04-10 05:27:37

这是使用@Xan 和@AmanicA 的解决方案在 Chrome 清单中使用“下载”权限下载文件的简洁方法

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"
});
非常感谢简洁,希望我早点注意到它。无需模拟对隐藏a标签的点击谢谢!
2021-04-08 05:27:37
这个脚本是在内容脚本或后台脚本中还是在其他地方?我在“chrome.downloads.download({
2021-04-12 05:27:37

Github上的Appmator代码中做了如下操作

基本方法是根据需要构建 Blob(Chrome 在 XmlHttpRequest 上有一个 responseBlob,因此您可以使用它),创建一个 iframe(隐藏display:none),然后将 iframe 的 src 分配为 Blob。

这将启动下载并将其保存到文件系统。唯一的问题是,您还不能设置文件名。

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);

使用 XmlHttpRequest 的 responseBlob 的示例(参见: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);
}
您如何将其设置为下载为正确的文件类型?Chrome 不断尝试将其下载为 html 文件。在其上创建 Blob 的页面也会冻结并崩溃。似乎 blob 的来源也是空白的。
2021-03-22 05:27:37
是的,你能编辑代码来展示如何做到这一点吗?我不知道把位置放在哪里。
2021-03-23 05:27:37
我在哪里指定我要下载的文件?
2021-04-03 05:27:37
那取决于你。它可能是 xhr 请求上的 responseBlob
2021-04-07 05:27:37
你能展示一些你正在尝试做的事情的示例代码,这使得它崩溃 - 很难说出你现在正在尝试做什么。我会说我添加了一小段代码来覆盖 mimetype。
2021-04-08 05:27:37