当前位置: 首页 > news >正文

前端文件下载的方式

方式一:a标签直接下载

<a href="链接" >下载</a>

一个文件链接(一般是服务器上的某个文件),这个链接一般地址栏输入是预览,不是附件下载

如果想改成附件下载,以下两种方式任选一个均可:
1、后端处理,后端加上一个响应头

res.setHeader('Content-Dispostion', 'attachment', 'name.pdf')

2、a标签 加上 download属性

<a href="链接" download="文件名" >下载</a>

方式一的缺点:

缺点:在 JavaScript 中使用 a 标签下载文件时,直接通过 a标签的点击事件触发下载,是无法设置请求头的,因为这是一个简单的 GET 请求。如果这个文件的下载要求的是携带token,那a标签这种就不生效了(a标签没法携带token),会成为预览。
方案:a标签可以携带cookie,所以可以有另一种解决方法,在下载文件前,发送一个请求获取一个临时token通过cookie进行携带,a标签下载是流式下载,会把服务器的文件像流水一样存储到本地磁盘,所以下载直接能看到下载,不会将文件缓存到浏览器。

标题方式二:使用 XMLHttpRequest 或 Fetch API 请求。

写一个方法进行下载 (本质还是利用a标签进行下载)
这个方法可以是一个ajax请求,这个请求就可以携带token,然后将请求到的服务器文件转成blob,在创建一个a标签进行下载,创建虚拟的链接元素,模拟点击下载。


import fetch from 'isomorphic-fetch';
const exportFile = (url, options) => {const projectId = sessionStorage.getItem(PROJECT_ID);const downLoadURL = projectId ? BATCH_ACTION_URL_PREFIX.V2 : BATCH_ACTION_URL_PREFIX.V1;const defaultOptions = {credentials: 'same-origin',};const newOptions = { ...defaultOptions, ...options };if (newOptions.method === 'POST' ||newOptions.method === 'PUT' ||newOptions.method === 'DELETE') {const projectId = sessionStorage.getItem(PROJECT_ID);const appId = sessionStorage.getItem(APP_ID);const shopId = sessionStorage.getItem(SHOP_ID);const params = {};projectId && Object.assign(params, { projectId });appId && Object.assign(params, { appId });shopId && Object.assign(params, { shopId });newOptions.body = { ...newOptions.body, ...params };if (!(newOptions.body instanceof FormData)) {newOptions.headers = {Accept: 'application/json','Content-Type': 'application/json; charset=utf-8',...newOptions.headers,};} else {// newOptions.body is FormDatanewOptions.headers = {Accept: 'application/json',...newOptions.headers,};}}const token = window.localStorage.getItem(TOKEN);if (token) {newOptions.headers = {'X-Authorization': `Bearer ${token}`,...newOptions.headers,};}const lang = localStorage.getItem(LOCALE_KEY);if (lang) {newOptions.headers = {'Accept-Language': lang,...newOptions.headers,};}const requestURL = `${downLoadURL}/${url}`;return request(requestURL, newOptions).then(res => {let filename;if (res.headers) {filename = (res.headers.get('Content-Disposition') || res.headers.get('content-disposition')).split('attachment;filename=')[1];}if (res.blob) {res.blob().then(blob => {var alink = document.createElement('a');alink.style.display = 'none';alink.target = '_blank';if (window.navigator && window.navigator.msSaveOrOpenBlob) {// 兼容IE/Edgewindow.navigator.msSaveOrOpenBlob(blob, filename);} else {alink.href = window.URL.createObjectURL(blob);alink.download = filename;}document.body.appendChild(alink);alink.click();URL.revokeObjectURL(alink.href); // 释放URL 对象document.body.removeChild(alink);});return res;} else {if (res.code === 0) {return res;} else {message.warning(res.message);}}});
};export default exportFile;export default function request(url: string, options: Object) {const defaultOptions = {credentials: 'same-origin',};const newOptions = { ...defaultOptions, ...options };if (newOptions.method === 'POST' ||newOptions.method === 'PUT' ||newOptions.method === 'DELETE' ||newOptions.method === 'PATCH') {if (!(newOptions.body instanceof FormData)) {newOptions.headers = {Accept: 'application/json','Content-Type': 'application/json; charset=utf-8',...newOptions.headers,};newOptions.body = JSON.stringify(newOptions.body);} else {// newOptions.body is FormDatanewOptions.headers = {Accept: 'application/json',...newOptions.headers,};}}return fetch(url, newOptions).then(response => checkStatus(response, url, options));
}

方式二的缺点:

**如果文件小还行,文件大了就会出现点击了下载,但是没有反应,过了几分钟后才出现了下载,这种等待时间就是将服务器端的那个文件转成了blob(res.blob()花的时间特别长),才进行a标签的流式下载(这里页面才开始出现有下载的交互体现)

http://www.lryc.cn/news/398126.html

相关文章:

  • 视图库对接系列(GA-T 1400)十六、视图库对接系列(本级)通知(订阅回调)
  • Python | Leetcode Python题解之第230题二叉搜索树中第K小的元素
  • Python酷库之旅-第三方库Pandas(018)
  • 九科bit-Worker RPA 内容学习
  • vscode编译环境配置-golang
  • 【JavaEE】网络编程——UDP
  • JAVA毕业设计147—基于Java+Springboot的手机维修管理系统(源代码+数据库)
  • 力扣第228题“汇总区间”
  • 部署大语言模型并对话
  • WebSocket、socket.io-client
  • Maven 仓库
  • 给后台写了一个优雅的自定义风格的数据日志上报页面
  • 【React Native优质开源项目】
  • Android 自动更新时间的数字时钟 TextClock
  • 【Linux Git入门】Git的介绍
  • kafka面试题(基础-进阶-高阶)
  • 《系统架构设计师教程(第2版)》第11章-未来信息综合技术-07-大数据技术概述
  • 前端面试题54(断点续传讲解)
  • YOLOv10改进 | Conv篇 | RCS-OSA替换C2f实现暴力涨点(减少通道的空间对象注意力机制)
  • 【C++BFS】690. 员工的重要性
  • 视频调整帧率、分辨率+音画同步
  • 【深度学习】关于模型加速
  • Python中time模块用法示例详解
  • 解决POST请求中文乱码问题
  • Axure-黑马
  • Centos解决服务器时间不准的问题
  • 摸鱼大数据——Kafka——Kafka的shell命令使用
  • 在 Linux/Debian/Ubuntu 上使用 Brasero 刻录光盘
  • QT之嵌入外部第三方软件到本窗体中
  • 解决GET请求中文乱码问题