使用h5 <a>标签 href='url' download 下载踩过的坑

本文探讨了跨域多媒体文件下载的限制及解决方法,包括利用后端转发、使用file-saver保存文件等,并分析了尝试绕过限制的方法及其可行性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

<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;
  };

结论:

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

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

 

<div data-v-4c755c92="" class="cool-video-wrapper"><div id="course-player" class="cool-player mobile aliplayer prism-player" x5-playsinline="" x-webkit-airplay="" playsinline="" webkit-playsinline="" style="width: 100%; height: 100%;"><video webkit-playsinline="" playsinline="" x-webkit-airplay="allow" x5-playsinline="" preload="preload" autoplay="autoplay" src="blob:https://nsxy1862.coolcollege.cn/e64c3025-8896-4ddf-82cc-894472da3d30" poster="https://oss.coolcollege.cn/1815458882630324224.png" x5-video-player-type="h5" style="width: 100%; height: 100%;"></video> <div class="cool-player-video-wrap"> <div class="cool-player-mask"> <!-- 视频加载loading --> <div class="cool-player-marker" style="display: none;"> <div class="loading"> <div class="rotate"></div> </div> </div> <!-- 中间的大播放按钮 --> <div class="cool-player-center" style="display: none;"> <span class="cool-player-big-play-btn"></span> <span class="cool-player-play-duration" style="display: none;"></span> </div> <!-- 视频手势拖动 显示的动态时间 --> <div class="cool-player-toast-progress"></div> <div class="cool-player-controller" style="visibility: hidden;"> <div class="controller"> <div class="controller-draggable-tips">视频未播放完,暂不允许快进</div> <div class="controller-button pause" style="display: inline-block;"></div> <div class="controller-button play" style="display: none;"></div> <!-- 当前时间 --> <div class="cool-player-current-time">01:59</div> <!-- 进度条 --> <div class="cool-player-progress"> <div class="progress-bar"> <div class="bar-buffered" style="width: 100%;"></div> <div class="progress-ball" style="left: 75.1511%;"> <div class="progress-inner"></div> </div> </div> </div> <!-- 总时长 --> <div class="cool-player-duration">02:38</div>帮我把这个视频下载下来
05-07
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值