Chrome 65 个跨域块 <a download>。强制下载的客户端解决方法?

Chrome 65 blocks cross-origin <a download>. Client-side workaround to force download?

Chrome 65 删除了对 download 属性的支持 在具有跨源的锚元素上 hrefs:

Block cross-origin <a download>

To avoid what is essentially a user-mediated cross-origin information leakage, Blink will now ignore the presence of the download attribute on anchor elements with cross origin attributes. Note that this applies to HTMLAnchorElement.download as well as to the element itself.

Intent to Remove | Chromestatus Tracker | Chromium Bug

这会中断 serverless downloads (for cross-origin resources). It has also broken Reddit Enhancement Suite's save image button (.res-media-controls-download) RES v5.12.0 fixed this by using the chrome.downloads API(该扩展程序现在请求您允许 管理下载

任何解决方法?

Web spec 中有更多详细信息,感谢@jbmilgrom

根据 discussion blob: and data: URLs are unaffected, so here is a workaround using fetch 和 Blobs.

Client-side 强制下载媒体

function forceDownload(blob, filename) {
  var a = document.createElement('a');
  a.download = filename;
  a.href = blob;
  // For Firefox https://whosebug.com/a/32226068
  document.body.appendChild(a);
  a.click();
  a.remove();
}

// Current blob size limit is around 500MB for browsers
function downloadResource(url, filename) {
  if (!filename) filename = url.split('\').pop().split('/').pop();
  fetch(url, {
      headers: new Headers({
        'Origin': location.origin
      }),
      mode: 'cors'
    })
    .then(response => response.blob())
    .then(blob => {
      let blobUrl = window.URL.createObjectURL(blob);
      forceDownload(blobUrl, filename);
    })
    .catch(e => console.error(e));
}

downloadResource('https://giant.gfycat.com/RemoteBlandBlackrussianterrier.webm');

但是,fetch 仅适用于某些网址。您可能会遇到 CORS 错误:

Failed to load https://i.redd.it/l53mxu6n14o01.jpg: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://redditp.com' is therefore not allowed access.

有一些扩展程序可以让您拦截和修改或删除网站的安全性 headers:

ModHeader - Chrome Web Store

(但设置 Access-Control-Allow-Origin: * 对我来说破坏了 YouTube)

性能

请注意,这种方法的性能不是很好!有时我的下载停滞时间不到 1 分钟。不过,页面的其余部分在此期间是响应式的。我没有研究过这个,但我想创建大型 Blob 会占用大量资源。

暴力猴子/篡改猴子

如果您的用例是用户脚本,则 GM_download(options), GM_download(url, name)

⚠ 在 Tampermonkey 中这是测试版功能,您必须先在 Tampermonkey 控制面板中设置 下载模式: [浏览器 API ▾] >设置

显然,web specification 已更改为禁止 cross-origin 下载。在响应中添加 content-disposition: attachment header,cross-origin 下载可能会再次运行。