前端页面下载(前端下载文件的方式)
导读:概要 在前端下载文件是个很通用的需求,一般后端会提供下载的方式有两种:...
概要
在前端下载文件是个很通用的需求 ,一般后端会提供下载的方式有两种:
直接返回文件的网络地址(一般用在静态文件上 ,比如图片以及各种音视频资源等) 返回文件流(一般用在动态文件上,比如根据前端选择 ,导出不同的统计结果 excel 等)第一种方式比较简单 ,但是使用场景有限 。
第二种方式通用性更好 ,最近再使用 antd 开发的过程中 ,下载文件部分折腾了一下午 ,于是将关键的部分和遇到的一些问题整理如下 。前端核心代码
我的前端是基于 antd pro 开发的 ,这里不在详细介绍 antd pro 相关的内容 ,只说明下封装的下载函数:
import { request } from "umi"; // 这是我在项目中封装的下载函数 ,有2个参数: // 一个是文件的id ,用来给后端API搜索文件用的 // 一个是文件名filename,这个给前端用的 ,下载时 ,默认保存的文件名 export async function DownloadFile(id: string, filename: string) { return RestGet<BlobPart>(`/api/v1/file/download/${id}`, "blob").then( (res) => { let url = URL.createObjectURL(new Blob([res], { type: "octet/stream" })); let a = document.createElement("a"); a.href = url; a.download = filename; a.click(); URL.revokeObjectURL(url); } ); } // GET 方式请求后端API export async function RestGet<T>( url: string, responseType: "json" | "blob" = "json" ) { return request<T>(url, { method: "GET", headers: { "Content-Type": "application/json", }, responseType: responseType, }); } // POST 方式请求后端API export async function RestPost<T>( url: string, body: any, responseType: "json" | "blob" = "json" ) { return request<T>(url, { method: "POST", headers: { "Content-Type": "application/json", }, data: body, responseType: responseType, }); }这个下载函数本质就是创建一个 元素,然后模拟点击此 元素来完成下载 。
对于 DownloadFile函数 ,我是根据自己的需要封装的 ,不一定非得是这两个参数,可以根据自己的后端 API 来定制需要传入的参数 。将下载封装成函数之后看 ,前端就可以通过一个按钮来下载文件了 ,比如:
<Button type="link" key="download" icon={<DownloadOutlined />} onClick={() => DownloadFile(item.video_file_id as string, (item.name as string) + ".mp4") } > 下载 </Button>我这里是 GET 方式下载文件的 ,如果参数比较多且复杂的话 ,也可以使用 POST 方式 。
只要把 DownloadFile中 RestGet<T>改成 RestPost<T> ,并调整相应的参数即可 。遇到的问题
调试其中的下载方式就不提了 ,遇到的最大困难 ,搜索半天也没什么人提到的就是请求中的 responseType问题 。
刚开始 ,我没有设置 responseType ,默认值好像是 json或者 text 。
测试时发现,下载文本类型的文件没有问题 ,但是下载二进制文件的话 ,比如视频或者图片,下载之后总是无法正常打开 ,前后端也没有任何错误提示 。折腾了半天 ,才试出 responseType传入 blob的话,二进制文件才能正常下载。
而且发现 ,设置成 blob的话 ,文本类型的文件也能正常下载打开 。创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!