简体   繁体   English

使Chrome扩展程序下载文件

[英]Making a Chrome Extension download a file

I am creating an extension that will download a mp3 file off a website. 我正在创建一个扩展程序,将从网站上下载mp3文件。 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. 我正在尝试通过创建带有指向mp3文件的链接的新标签来实现此目的,但是chrome会继续在播放器中打开它而不是下载它。 Is there any way I can create a pop-up to ask the user to "save-as" the file? 有什么方法可以创建一个弹出窗口,要求用户“另存为”文件?

Fast-forward 3 years, and now Google Chrome offers chrome.downloads API (since Chrome 31). 快进了3年,现在Google Chrome提供了chrome.downloads API (自Chrome 31起)。

After declaring "downloads" permission in the manifest, one can initiate a download with this call: 在清单中声明"downloads"权限后,可以通过以下调用启动下载:

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, eg: 如果要在脚本中生成文件内容,则可以使用BlobURL 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 (ie Save As dialog, overwriting existing files, etc.), see the documentation . 有关更多选项(例如,另存为对话框,覆盖现有文件等),请参见文档

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. 您需要记住的一件事是,此代码需要在页面而不是您的扩展名上执行-否则用户将看不到chrome所执行的下载操作。 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" . 在内容页面而不是扩展程序上执行操作的方法是使用Chrome “消息传递” 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);
          }
      }
  });

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
}

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

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(hidden, display:none ),然后将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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM