赞
踩
<a href="//example.com/resource" download="filename.ext"> 下载 </a>
attr download
可以指定下载资源(默认)文件名,但仅在同源时有效。
非同源,但允许跨域时,我们同样可以直接使用 a tag:
<a href="//example.com/resource" target="_self"> 下载 </a>
要注意的是,点击链接后浏览器进行下载文件的主要行为主要依赖于下面这几个因素:
服务端响应头 Content-Disposition
,它可以影响下列行为:
Content-Disposition: attachment
Content-Disposition: attachment; filename="filename.jpg"
Content-Disposition: inline
服务端响应头 Content-Type
会影响下载文件的文件名后缀。
attr target
为 "_blank"
有时会影响服务端的 Content-Type
头,使用 "_self"
时正常。
case:前者得到的该响应头 value 为 application/octet-stream
,导致文件扩展名推断错误(消失)。
通过 xhr/fetch 将资源拉到浏览器内存中,然后再触发浏览器的下载流程。
需要在下载过程中给用户以视觉反馈。
const fetchBlob = (url: string): Promise<Blob> => new Promise((resolve, reject) => { const xhr = new XMLHttpRequest() xhr.open('GET', url, true) xhr.responseType = 'blob' xhr.onload = () => { if (xhr.status === 200) resolve(xhr.response) else reject(xhr.statusText) } xhr.send() }) export const saveAsAnyFilename = async (originUrl: string, filename: string): Promise<void> => { try { const blob = await fetchBlob(originUrl) if ((window.navigator as any).msSaveOrOpenBlob) { // IE (navigator as any).msSaveBlob(blob, filename) } else { // modern browsers const link = document.createElement('a') document.body.appendChild(link) link.href = URL.createObjectURL(blob) link.download = filename link.style.display = 'none' link.click() window.URL.revokeObjectURL(link.href) document.body.removeChild(link) } } catch { try { copy(originUrl) toast.success('下载失败, 已复制下载链接, 请手动下载') } catch { Modal.success({ title: '下载失败, 请手动复制链接下载', content: originUrl, }) } } }
几乎只能通过服务端代理请求目标资源,可能存在其他比较 hack 的方案,暂时还没找到。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。