Javascript 使Chrome扩展下载文件

Javascript 使Chrome扩展下载文件,javascript,html,google-chrome,google-chrome-extension,Javascript,Html,Google Chrome,Google Chrome Extension,我正在创建一个扩展,可以从网站下载mp3文件。我试图通过创建一个带有mp3文件链接的新标签来实现这一点,但chrome一直在播放器内部打开它,而不是下载它。是否有任何方法可以创建一个弹出窗口,要求用户“另存为”文件?我在上的代码中按如下方式操作 基本方法是根据需要构建Blob(Chrome在XmlHttpRequest上有一个responseBlob,您可以使用它),创建一个iframe(隐藏,display:none),然后将iframe的src指定为Blob 这将启动下载并将其保存到文件系统

我正在创建一个扩展,可以从网站下载mp3文件。我试图通过创建一个带有mp3文件链接的新标签来实现这一点,但chrome一直在播放器内部打开它,而不是下载它。是否有任何方法可以创建一个弹出窗口,要求用户“另存为”文件?

我在上的代码中按如下方式操作

基本方法是根据需要构建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);

我在溶液中使用了一种变体

你需要记住的一点是,这段代码需要在页面上执行,而不是在你的扩展上执行——否则用户将看不到chrome所做的下载操作。下载仍然会发生,您可以在下载选项卡中看到它,但他们不会看到实际的下载发生

编辑(在内容页上执行代码后考虑):

在内容页而不是扩展页上执行操作的方式是使用Chrome。基本上,您可以将一条消息从扩展(几乎像一个单独的页面)传递到扩展正在使用的内容页面。然后,您的扩展将一个侦听器注入到内容页中,该内容页对消息做出反应并进行下载。大概是这样的:

chrome.extension.onMessage.addListener(
  function (request, sender, sendResponse) {  
      if (request.greeting == "hello") {
          try{
              downloadCSS();
          }
          catch (err) {
              alert("Error: "+err.message);
          }
      }
  });

这是@Steve Mc答案的一个稍加修改的版本,只是将其变成了一个通用函数,可以轻松复制并按原样使用:

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
}

快进3年,现在谷歌Chrome提供(自Chrome 31)

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

chrome.downloads.download({
  url: "http://your.url/to/download",
  filename: "suggested/filename/with/relative.path" // Optional
});
如果要在脚本中生成文件内容,可以使用和API,例如:

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

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

这里有一个简明的方法,可以使用@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"
});

请看我在哪里指定要下载的文件?这取决于您。它可能是xhr请求上的responseBlob耶,您可以编辑代码来演示如何做到这一点吗?我不知道该把位置放在哪里。你如何设置它作为正确的文件类型下载?Chrome一直试图将其作为html文件下载。创建blob的页面也会冻结并崩溃。blob的源代码似乎也是空的。你能给出一些示例代码,说明你正在尝试做什么,这会使它崩溃吗?很难说出你现在正在尝试做什么。我想说我添加了一小段代码来覆盖mimetype。谢谢!是否可以让Chrome将文件附加到现有文件中?我想下载一个由片段组成的文件,从而生成一个完整的文件,而不是多个片段。@marlar为此,最好使用(尽管有警告,Chrome支持)获取块,构建完整的文件,然后
将结果下载到下载文件夹中。但这是一个不同的问题;如果您仍然需要帮助,请问一个新问题。“文件名”在我的系统中完全被忽略@Xan我遇到了这个错误:
未检查的runtime.lastError在运行下载时。下载:无效文件名
有什么想法吗?@anunixercoder可能已经发现了这个问题,但是对于后面的人来说:这个代码需要在
background.js上,它在
content.js
上不适用于当前用户:SteveMC的答案不再有效,但这个答案有效
不做您认为它在这里做的事情,您实际上需要
a.parentNode.removeChild(a)。(删除对a的引用是不必要的,因为作为局部变量,它在函数完成时会丢失)。您是否知道这是否仍然有效?,
chrome.downloads
没有按照我希望的方式工作。仍然有效,但遇到了与chrome下载相同的问题。Chrome不允许扩展下载多个文件。非常感谢这种简洁,希望我能早点注意到。无需模拟单击隐藏的
a
标记。谢谢这个脚本是在内容脚本、背景脚本还是其他地方?我在“chrome.downloads.download”行上得到一个“uncaughttypeerror:无法读取未定义”的属性“download”({
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
  //...
});
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"
});