使用h5 <a>标签 href='url' download 下载踩过的坑_<a id="downloadurl" href="">-程序员宅基地

技术标签: html笔记  

用户点击下载多媒体文件(图片/视频等),最简单的方式:

<a href='url' download="filename.ext">下载</a>

如果url指向同源资源,是正常的。

如果url指向第三方资源,download会失效,表现和不使用download时一致——浏览器能打开的文件,浏览器会直接打开,不能打开的文件,会直接下载。浏览器打开的文件,可以手动下载。

解决方案一:将文件打包为.zip/.rar等浏览器不能打开的文件下载。

解决方案二:通过后端转发,后端请求第三方资源,返回给前端,前端使用file-saver等工具保存文件。

 

如果url指向的第三方资源配置了CORS,download依然无效,但可以通过xhr请求获取文件,然后下载到本地。

/**
 * 用FileSave保存文件
 * @param url
 */
export function downloadUrlFile(url) {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.responseType = 'blob';
  xhr.setRequestHeader('Authorization', 'Basic a2VybWl0Omtlcm1pdA==');
  xhr.onload = () => {
    if (xhr.status === 200) {
      // 获取图片blob数据并保存
      saveAs(xhr.response, 'abc.jpg');
    }
  };

  xhr.send();
}

/**
 * URL方式保存文件到本地
 * @param name 文件名
 * @param data 文件的数据
 */
function save(name, data) {
	var urlObject = window.URL || window.webkitURL || window;
	var export_blob = new Blob([data]);
	var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a')
	save_link.href = urlObject.createObjectURL(export_blob);
	save_link.download = name;
	_fakeClick(save_link);
}

 

第三方跨域多媒体资源无法直接下载。很奇怪,浏览器不能打开的文件可以下载,浏览器能打开的文件不能下载,这个限制似乎没有多大意义。

不依靠后端,有两个可能破解这个限制的思路。

1、window.open(url),再向新窗口写入一个<a href='url' downlad></a>,触发点击。

验证结果:这种向别人的网页中嵌入自己内容的方式,极大影响浏览器的安全,无法实现。

2、<img src='url'  οnlοad='onload'>, onload的回调中,将img 绘入 canvas,canvas.toDataUrl(),然后保存。

MDN给出的例子        使用download保存画布为png

验证结果:canvas.drawImage(img,0,0)后,canvas被跨域资源污染,canvas.toDataUrl()调用报错。

/**
   * 下载url图片
   * @param imageUrl
   */
  const downloadUrl = (imageUrl) => {
    const downloadCanvas = $('#download-canvas')[0];
    const img = new Image();
    img.onload = () => {
      const ctx = downloadCanvas.getContext('2d');
      ctx.drawImage(img, 0, 0);
      const imageDataUrl = downloadCanvas.toDataURL('image/jpeg'); 
      // Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
      saveAs(imageDataUrl, '附件');
    };
    img.src = imageUrl;
  };

结论:

浏览器已经限制死跨域下载多媒体文件的各种方式。

最正规的办法还是让后端做一次转发。请求后端,后端向第三方请求文件,返回给前端,前端保存文件。

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yiyan12/article/details/80902945

智能推荐

LightOJ - 1067 Combinations(快速幂+逆元)_快速幂求逆元 在线oj-程序员宅基地

文章浏览阅读484次。DescriptionGiven n differentobjects, you want to take k of them. How many ways to can do it? For example, saythere are 4 items; you want to take 2 of them. So, you can do it 6 ways. Take 1, _快速幂求逆元 在线oj

Fairseq学习日记:注定麻烦的旅程_final_lr_scale-程序员宅基地

文章浏览阅读6.6k次,点赞10次,收藏23次。现在开头:Fairseq是一个正在快速迭代的产品,而且是开源的!这不是表扬,这意味着三件事情:1.他没有文档!所有框架代码都没有任何注释,包括函数docstring都没有2.他没有经过有效测试,估计是抢时间吧!即使是官网Readme里的例子也是无法跑起来的!3.他是一个框架,而且是一个非常不Pythonic的框架,充斥着inline/包装器/莫名其妙的语法。虽然这三点决定他真的对不住Facebook的金字招牌,但是作为一个学习者,总要把他运行起来,那么开始这场针对 FaceBOOK派“全_final_lr_scale

[Linux][Busybox]分享你不知道Top 命令参数_busybox top-程序员宅基地

文章浏览阅读5.1k次。目录摘要:基本操作与命令介绍:进入top后交互一点点新的操作Author: Keivn.Xu [email protected]摘要: 玩过Linux一定使用过busybox top命令,但下面的操作方法,你不一定有见过。基本操作与命令介绍:console:/ $ busybox top -help top: invalid optio..._busybox top

rssi参数获取_信号强度(RSSI)知识整理-程序员宅基地

文章浏览阅读1.6k次。为什么无线信号(RSSI)是负值答:其实归根到底为什么接收的无线信号是负值,这样子是不是容易理解多了。因为无线信号多为mW级别,所以对它进行了极化,转化为dBm而已,不表示信号是负的。1mW就是0dBm,小于1mW就是负数的dBm数。弄清信号强度的定义就行了:RSSI(接收信号强度)Received Signal Strength IndicatorRss=10logP,只需将接受到的信号功率P代..._c#获取低功耗设备的rssi信号强度

后端服务的雪崩效应及解决思路_接口超时时间过长导致雪崩效应-程序员宅基地

文章浏览阅读204次。1.RPC与本地调用的区别RPC远程调用,一般是跨平台、采用http协议,因为http协议底层使用socket技术,只要你的语言支持socket技术,就可以相互进行通讯。比如:java语言开发的接口,使用http协议,如此以来C#语言可以调用。本地调用:只支持java语言与java语言开发,使用虚拟机和虚拟机之间的通讯,RMI。2.雪崩效应产生的原因默认情况下只有一个线程池维护所有的服务接口,如果大量的请求访问同一个接口,达到tomcat线程池默认极限,可能会导致其他服务无法访问。3.雪_接口超时时间过长导致雪崩效应

linux操作redis_linux 连接redis-程序员宅基地

文章浏览阅读2.7w次,点赞4次,收藏35次。redis常用命令_linux 连接redis

随便推点

js获取年月日 时分秒的日期格式_js 时分秒 时间格式-程序员宅基地

文章浏览阅读1.1k次。const date = new Date()const year = date.getFullYear()const month = date.getMonth() + 1 >= 10 ? date.getMonth() + 1 : `0${date.getMonth() + 1}`const day = date.getDate() >= 10 ? date.getDate() : `0${date.getDate()}`const hours = date.getHours() ._js 时分秒 时间格式

【模拟】Oracle重建索引_oracle 重建索引-程序员宅基地

文章浏览阅读2.2k次。摘要:简述重建索引的情况及重建索引_oracle 重建索引

keil迁移到cubeIDE_cubeide生成代码 keil打开-程序员宅基地

文章浏览阅读2.7k次。以stm32f105rct6为例子,keil迁移到cubeIDE_cubeide生成代码 keil打开

语音处理:Python实现dBFS刻度和采样值相互转换_dbfs 频域-程序员宅基地

文章浏览阅读781次。以对数域常用的dBFS刻度为例,支持主流音频信号位深:整型16/24/32位和浮点32位,编写Python实现对数域和采样值单位互换功能_dbfs 频域

SOD(显著性目标检测)数据集_sod数据集-程序员宅基地

文章浏览阅读4k次,点赞5次,收藏29次。显著性目标检测常用十种数据集:SOD,提取码:f7uqDUT-OMRON,提取码:wqpnMSRA-B,提取码:rfrbSOC,提取码:d5b9SED2,提取码:q4iaHKU-IS,提取码:2f1iPASCAL-S,提取码:naaxDUTS,提取码:a5w7THUR-15K,提取码:ptk9ECSSD..._sod数据集

线程基础:多任务处理(18)——MESI协议以及带来的问题:伪共享-程序员宅基地

文章浏览阅读3.9k次,点赞10次,收藏17次。本文和后续文章将着眼CPU的工作原理阐述伪共享的解决方法和volatile关键字的应用。