使Chrome扩展程序下载文件

时间:2022-10-24 10:40:08

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?

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

5 个解决方案

#1


76  

Fast-forward 3 years, and now Google Chrome offers chrome.downloads API (since Chrome 31).

快进3年,现在谷歌Chrome提供chrome.downloads API(自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.:

如果要在脚本中生成文件内容,可以使用Blob和URL 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
  //...
});

For more options (i.e. Save As dialog, overwriting existing files, etc.), see the documentation.

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

#2


13  

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.

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

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“消息传递”。基本上,您将消息从您的扩展程序(几乎就像一个单独的页面)传递到扩展程序正在使用的内容页面。然后,您有一个监听器,您的扩展已注入内容页面,该页面对消息作出反应并进行下载。像这样的东西:

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

#3


9  

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:

这是@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
}

#4


5  

I did it as follows in Appmator code on Github.

我在Github上的Appmator代码中做了如下。

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.

基本方法是构建你的Blob,无论你想要什么(Chrome在XmlHttpRequest上有一个responseBlob,你可以使用它),创建一个iframe(隐藏,显示:无),然后将iframe的src指定为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)

使用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);
}

#5


4  

Here's a concise way to download a file using "downloads" permission in Chrome manifest using @Xan and @AmanicA's solution

以下是使用@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"
});

#1


76  

Fast-forward 3 years, and now Google Chrome offers chrome.downloads API (since Chrome 31).

快进3年,现在谷歌Chrome提供chrome.downloads API(自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.:

如果要在脚本中生成文件内容,可以使用Blob和URL 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
  //...
});

For more options (i.e. Save As dialog, overwriting existing files, etc.), see the documentation.

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

#2


13  

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.

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

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“消息传递”。基本上,您将消息从您的扩展程序(几乎就像一个单独的页面)传递到扩展程序正在使用的内容页面。然后,您有一个监听器,您的扩展已注入内容页面,该页面对消息作出反应并进行下载。像这样的东西:

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

#3


9  

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:

这是@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
}

#4


5  

I did it as follows in Appmator code on Github.

我在Github上的Appmator代码中做了如下。

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.

基本方法是构建你的Blob,无论你想要什么(Chrome在XmlHttpRequest上有一个responseBlob,你可以使用它),创建一个iframe(隐藏,显示:无),然后将iframe的src指定为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)

使用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);
}

#5


4  

Here's a concise way to download a file using "downloads" permission in Chrome manifest using @Xan and @AmanicA's solution

以下是使用@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"
});