href标签下载属性-如何使其强制下载外部托管图片?

时间:2018-09-23 11:54:41

标签: javascript html html5 download href

我想创建一个<a href链接,单击该链接会强制浏览器打开“另存为”对话框。在所有现代浏览器上,使用HTML5 download属性都应具有这种行为。

如果目标是外部托管的图像文件,则此操作无效。 <a href链接将导航到该图像,而不是下载它。 (使用Imgur和Tumblr上托管的图像进行了测试)

<a href="https://i.stack.imgur.com/440u9.png" download>
  <img src="https://i.stack.imgur.com/440u9.png" width="200"/>
</a>
例如,如果图像是在您的服务器上本地托管的,则

类似的HTML代码是有效的有效

<a href="440u9.png" download>
  <img src="440u9.png" width="200"/>
</a>

另一个示例-这将在W3Schools Tryit Editor中起作用,但如果将HTML复制到另一个沙箱(如JSFiddle),则不会起作用

<a href="https://www.w3schools.com/images/myw3schoolsimage.jpg" download>
  <img src="https://www.w3schools.com/images/myw3schoolsimage.jpg" width="104" height="142">
</a>


探究的可能原因:

  • 不良图片网址:否,该网址很好,您可以在浏览器中将其作为普通图片打开
  • 出于安全考虑,无法以这种方式使用https:链接:否,如果URL指向相同的域(在W3Schools Tryit编辑器中测试过),则该URL为https:很好>
  • 服务器端重定向:可以将http://...链接重定向到https://...,所以这可能是失败的原因,但是https://...链接也不起作用< / em>
  • 特定主机是否抑制服务器上的下载属性? 那有可能吗? download属性应该确定只能控制客户端浏览器的操作吗?

有任何解决方法吗?我已经尝试过讨论herehere的Javascript下载方法,但这些方法最终都涉及到类似于单击href链接的浏览器操作。

Excellent in-depth discussion of download links,包括服务器上PHP中的application/force-download设置

与StackOverflow相关的问题:Force external download url(答案似乎不正确)

2 个答案:

答案 0 :(得分:1)

我的解决方法:将图像下载到画布,然后将画布图像下载到本地驱动器。

代码:

    <canvas id="downloadCanvas"></canvas>

    <script>
        var strDataURI = "https://78.media.tumblr.com/33f1b72778ca7352979b0f4555f08f02/tumblr_pfega8eUyH1r68v93o1_640.jpg";
        var img = new Image;
        img.crossOrigin = "Anonymous";
        img.src = strDataURI;


        var canvas = document.getElementById('downloadCanvas');
        var ctx = canvas.getContext('2d');

        img.onload = function(){

          canvas.width = img.width;
          canvas.height = img.height;
          ctx.drawImage(img,0,0);

          var dwBtn = document.getElementById("dw0");
            var dwLink = canvas.toDataURL('image/jpeg', 1.0);

          download(dwLink, "image.jpeg");
        };


    function download(dataurl, filename) {
      var a = document.createElement("a");
      a.href = dataurl;
      a.setAttribute("download", filename);
      var b = document.createEvent("MouseEvents");
      b.initEvent("click", false, true);
      a.dispatchEvent(b);
      return false;
    }

</script>

按照OP的要求,他需要捕获的图像具有相同的扩展名。 (伪代码)

更改这些行:

  var ext = ExtensionFromUrl(url);
  var fileName = NameFromUrl(url);

      var dwLink = canvas.toDataURL('image/'+ext, 1.0);
      download(dwLink, fileName+"."+ext);

请注意:此答案不适用于GIF图像。另外,由于它们是捕获的图像,因此透明通道也会丢失!

答案 1 :(得分:0)

得出的答案是无法以我的询问方式进行。现代浏览器将跨域下载作为一项安全功能来阻止。

请参阅: Making Firefox and Chrome download image under a specific name

Force <a download /> to download image instead of opening url link to image

如果下载必须与原始文件字节相同,那么我现在可以找到的唯一解决方案是:

  1. 服务器必须首先使用httpClient请求获取目标资源,将其保存到服务器上的本地磁盘,然后提供一个<a href='tmp.jpg' download>链接,其中包含已保存文件的URI。或者,某些服务器框架能够创建一个模拟文件访问的字节流,在这种情况下,资源可以缓存到内存中,而不是保存到磁盘中。

    缺点:数据成本等于文件大小的两倍(一次一次,一次一次),往返延迟,服务器内存/文件系统的使用。提供页面之前,可能每个带有下载链接的文件都必须存储在服务器上 上(或者可以使用websocket异步完成,在用户单击下载链接后提供文件,但有延迟)。对于大文件或高使用率的服务器,这些都是严重的缺点。

  2. 在新选项卡中打开目标URL,然后让客户端切换到该选项卡,然后手动右键单击并另存为...

    缺点:这正是我们要避免的事情!

我仍然想知道是否存在一些黑客手段,例如提供本地URL并让服务器将对该特定资源的请求重定向到外部站点。