【发布时间】:2020-07-23 12:03:40
【问题描述】:
我正在尝试制作一个 Chrome 扩展,通过 chrome.downloads.download 可以启动下载并指定生成的本地文件的文件名 - 特别是指定下载结果的文件扩展名。
如果服务器为此文件通告内容类型为 application/octet-stream,则可以正常工作。
但是,如果服务器发布了一些其他内容类型(例如 application/zip),则下载对象被设置为具有该 MIME 类型,并且下载的文件名被强制具有相关的扩展名(例如“. zip") 而不是我指定的那个。
我已尝试使用 onHeadersReceived 更改传入标头中的内容类型,将其强制为 application/octet-stream,但下载对象最终仍具有原始 MIME 类型并且文件扩展名仍是强制的。
使用 chrome.downloads.onDeterminingFilename 来“建议”我想要的文件名+扩展名也无助于防止强制扩展。我已经禁用了所有其他扩展,还检查了 onActionIgnored 是否会触发(它不会触发)。我终于为所有其他 webRequest 回调添加了日志记录,以查看是否有任何其他行为可以解释成功和失败案例之间的差异,但这个内容类型/mimetype 问题似乎是罪魁祸首。
这是在 Linux(基本操作系统,Ubuntu 变体)上加载到 Chrome 84.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>"
]
}
这是去掉所有调试繁琐的 background.js:
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"]
);
这些是我目前用来运行测试的文件。如果我右键单击“使用 octet-stream MIME 类型进行测试”并选择“测试 DL 重命名”,则会根据需要生成名为“test.zip.qz”的下载。右键单击“test with zip MIME type”会得到“test-mime.zip.zip”而不是“test-mime.zip.qz”。
【问题讨论】: