Google chrome extension Chrome extension正在下载can';不总是指定文件扩展名吗?

Google chrome extension Chrome extension正在下载can';不总是指定文件扩展名吗?,google-chrome-extension,Google Chrome Extension,我正在尝试创建一个Chrome扩展名,通过Chrome.downloads.download可以启动下载并指定生成的本地文件的文件名,特别是指定下载结果的文件扩展名 如果服务器为该文件播发内容类型为application/octet的流,则可以正常工作 但是,如果服务器播发某些其他内容类型(例如application/zip),则下载对象将设置为该MIME类型,并且下载的文件名将强制具有相关扩展名(例如“.zip”),而不是我指定的扩展名 我曾尝试使用onHeadersReceived更改传入标

我正在尝试创建一个Chrome扩展名,通过Chrome.downloads.download可以启动下载并指定生成的本地文件的文件名,特别是指定下载结果的文件扩展名

如果服务器为该文件播发内容类型为application/octet的流,则可以正常工作

但是,如果服务器播发某些其他内容类型(例如application/zip),则下载对象将设置为该MIME类型,并且下载的文件名将强制具有相关扩展名(例如“.zip”),而不是我指定的扩展名

我曾尝试使用onHeadersReceived更改传入标头中的内容类型,将其强制为application/octet流,但下载对象仍然具有原始MIME类型,并且文件扩展名仍然是强制的

使用chrome.downloads.OnDetermingFileName“建议”我所需的文件名+扩展名也无助于防止强制扩展。我已经禁用了所有其他扩展,还检查了onActionIgnored是否触发过(它没有)。最后,我为所有其他webRequest回调添加了日志记录,以查看是否有任何其他行为可以解释成功和失败案例之间的差异,但这个内容类型/mimetype问题似乎是罪魁祸首

这是一个在Linux(基本操作系统,Ubuntu的一个变种)上加载到Chrome84.0.4147.89的未打包扩展。我将在下面详细介绍扩展代码,但我认为可能只是关于如何创建下载对象的流程,这是a)不可能做到的,或者b)意味着我需要以其他方式做到这一点

谢谢你的帮助

以下是我的测试扩展的清单:

{
    "name": "Test DL Rename",
    "version": "1.0",
    "manifest_version": 2,
    "description": "Add a file extension to the name of a download.",
    "background": { 
      "scripts": ["background.js"],
      "persistent": true
    },
    "permissions": [
      "contextMenus",
      "downloads",
      "webRequest",
      "webRequestBlocking",
      "<all_urls>"
    ]
}
{
“名称”:“测试DL重命名”,
“版本”:“1.0”,
“清单版本”:2,
“说明”:“将文件扩展名添加到下载的名称中。”,
“背景”:{
“脚本”:[“background.js”],
“持久”:正确
},
“权限”:[
“上下文菜单”,
“下载”,
“网络请求”,
“webRequestBlocking”,
"

  • 看起来像是Chrome处理下载的一个有意的限制,以确保“安全”,你可以通过宣传你的用例来竞争

    同时,自己下载blob并更改其类型:

    chrome.contextMenus.onClicked.addListener(异步({linkUrl:url})=>{
    const blob=await(await-fetch(url)).blob();
    const typedBlob=blob.type===“应用程序/八位字节流”?blob:
    新Blob([Blob],{type:'application/octet stream'});
    chrome.downloads.download({
    url:url.createObjectURL(typedBlob),
    文件名:url.substring(url.lastIndexOf('/')+1)+'.qz',
    冲突行为:“不公平”,
    });
    });
    
    另外,现在您不需要webRequest API,您可以在manifest.json中使用
    “persistent”:false
    (FWIW有一种方法可以通过将
    webRequest
    放入
    可选的\u权限中,同时使用这两种权限,请参见)

    const CONTEXT_MENU_ID = "TEST_DL_RENAME";
    
    // add our thing to the context menu for links
    chrome.contextMenus.create(
      {
        id: CONTEXT_MENU_ID,
        title: "Test DL Rename",
        contexts: ["link"]
      }
    );
    
    // test download-renaming by adding ".qz" extension to downloaded file
    chrome.contextMenus.onClicked.addListener(
      function(info, tab) {
        if (info.menuItemId !== CONTEXT_MENU_ID) {
          return;
        }
        filename = info.linkUrl.substring(info.linkUrl.lastIndexOf('/') + 1);
        qzFilename = filename + ".qz";
        console.log("specifying name for download: " + qzFilename);
        chrome.downloads.download(
          {
            url: info.linkUrl,
            filename: qzFilename,
            conflictAction: "uniquify"
          },
          function(downloadId) {
            console.log("started download ID " + downloadId);
          }
        );
      }
    );
    
    // test setting content-type on a received download
    chrome.webRequest.onHeadersReceived.addListener(
      function(details) {
        // if doing this for real, we'd track which URLs we actually want to change
        // for now just change anything that is a zipfile
        if (details.url.split('.').pop() != "zip") {
          return {};
        }
        for (var i = 0; i < details.responseHeaders.length; i++) {
          if (details.responseHeaders[i].name.toLowerCase() == "content-type"){
            console.log("forcing content-type to application/octet-stream");
            details.responseHeaders[i].value = "application/octet-stream";
            break;
          }
        }
        return {
          responseHeaders: details.responseHeaders
        };
      },
      {
        urls: ["<all_urls>"]
      },
      ["blocking", "responseHeaders"]
    );