vue实现文件下载、导出、前端多种方式实现文件下载

前端开发中,经常遇到文件下载的功能。这里对常见的文件下载方式做一些总结。

前端下载通常分为两种情形,一种是后端直接给一个文件地址,通过浏览器打开就可以下载,另外一种则需要发送请求,后端返回二进制流数据,前端解析流数据,生成URL,实现下载。


一、后端直接返回文件路径进行下载

1、普通文件地址

情况1、直接下载 - 针对一些浏览器无法识别的文件格式

针对一些浏览器无法识别的文件格式(如pdf、xls、ppt)。可以直接在地址栏上输入URL即可触发浏览器的下载功能。

* 地址栏输入文件URL
* window.location.href = URL
* window.open(URL)

该方式将下载逻辑放在后端处理,后端给出固定的url,前端使用window.location.herf下载
路径可以是相对路径也可以是绝对路径

情况2、直接下载 (使用a标签download属性)

直接下载仅支持使用的浏览器无法识别的文件。如果是浏览器支持的文件格式(如:html、jpg、png、mp4、mp3)等。则不会触发文件下载,而是被浏览器直接触发解析展示。

针对这种情况,我们可以使用a标签的download属性,可以设置成文件的文件名。

<a  :href="scope.row.vPath" :download="scope.row.vName" class="downloadBtn">
      <el-button type="text">{{ $t("message.work.Download") }}</el-button>
</a>

2、OSS存储方式的文件地址

这种方式的文件地址被访问时,访问文件路径默认是下载还是预览跟后端设置的服务器配置有关。
如果访问oss地址的文件只能预览,那么这种文件要下载的解决方式:



举个例子:
在阿里云 oss 通过链接下载文件 而不是 直接打开链接文件 在页面中显示
通过 a 标签下载 oss 中的文件,需要在连接的后面添加 response-content-type=application/octet-stream 的参数 就可以直接下载了

<a href="http://oss.com.cn?response-content-type=application/octet-stream" target="_blank" download="" ></a>


二、通过后端接口返回流,前端对流进行文件预览 or 文件下载

通过接口的方式,前端首先要将接口的返回头设置为blob方式,然后解析二进制流

具体实现步骤:

1、axios 设置响应头 responseType: 'blob',
export function downloadExcelApi(data) {
  return request({
    url: prefix + `/member/download/template/?tenantCode=${data.tenantCode}`,
    method: 'get',
    responseType: 'blob',  // 这里相应的要在request接收
    data
  });
}

这里可以在axios拦截器中设置d1响应头,可以设置 延长超时时间、加载动画,例如:

const service = axios.create({
  baseURL: config.BASE_API,  //
  timeout: 30000 // 请求超时
});

service.interceptors.request.use(
  (config) => {
     var xtoken = localStorage.getItem('loginToken');
      if (xtoken != null) {
        config.headers['X-User'] = xtoken;
        config.headers['System'] = 'M';
        config.headers['crmversion'] = 'V1.0.0';
        config.headers['channel'] = 'PC';
        config.headers['Content-Type'] = 'application/json';
      }
      if (config.responseType === 'blob') {
          config.timeout = 60000;
          loadingInstance = Loading.service({
              lock: true,
              text: 'Loading',
              spinner: 'el-icon-loading',
              background: 'rgba(0, 0, 0, 0.7)'
          });
       }

   //  ....................
})


service.interceptors.response.use( 
 (response) => {
     if (response.config.responseType === 'blob') {
        // 下载时直接返回blob
        loadingInstance && loadingInstance.close();
        return response.data;
      }

     // ................
})



解析二进制流,下载和预览是两种不同的处理:

处理1:请求后的二进制流转为下载文件

// 根据路径下载文件流
    fileDown(row) {
      console.log('根据路径下载文件流', this.url(row.signDocumentPath) , row.documentName)
      const params={
        filePath: this.url(row.signDocumentPath),
      }
      API_Audit.downloadFile(params).then((res)=>{
          const url = window.URL.createObjectURL(new Blob([res]))
          const name = `${row.documentName}`
          const link = document.createElement('a')
          link.style.display = 'none'
          link.href = url
          link.setAttribute('download', name)
          document.body.appendChild(link)
          link.click()
      })
    },

      const res = await this.$api.user.downloadExcelApi({ tenantCode: tenantInfo.code })
      const url = window.URL.createObjectURL(new Blob([res]))
      const name = '用户导入模板.xlsx'
      const link = document.createElement('a')
      link.style.display = 'none'
      link.href = url
      link.setAttribute('download', name)
      document.body.appendChild(link)
      link.click()


处理2:请求后的blob转为文件预览

const blob = new Blob([res], { type: 'application/pdf;chartset=UTF-8' })
const r = new FileReader();
r.readAsText(blob);
const url = window.URL.createObjectURL(blob)
window.open(url);


后台返回的二进制数据文件流格式如图:

image.jpeg

参考这个样子

PK����}�S�_rels/.rels���J�1��_%̽�m��iڋ�������?�&����ooЃ�l�B���|��I��ɏ�R�9�XV5(
�]�Z�����=�,�����@`�n�/4�����1���@'���ζ#���H�t�N�������-�U]������L�s���-A�1�$��Q�p�ޘ��`K�3�%��4��G��OAf�O&@ϻ�~]����e�c��MB��[Ē@Iz��nf�,'����Gў��
~S/����:da��+�PO��ѷ�|�PK�{<�$���PK����}�S�[Content_Types].xml�T�n�0�����*6�PU��C������\{C,���P��n�TJ%*��Ǚٙ�(�h�v�ZA�&��
��U�U�����6{�oY�Qz-m��0��d<�m"�F}nX���Ȫ�'3��<!mHN"m�\D��r��z0��*x��5��l<z�V.-V���t�d��(��J�����w�<�-�ܙ������5�lOChf����~Os/�K2���-��Q��Z:��Ыj�uLDLh`�s*�>KG���SB� i~��W-*$8ʰ'��wZ����qօzN���H�;t��N&Я��M��cm����s�����P�s:#}�pȪ����ʝ4�P�����!,.��;������EY�{��g6��PK�G��R�
�PK����}�S�docProps/app.xml��AN�0�E����uR!�"���B���k�LZK�m�CT8��X q�6p�@��'UK
�������F��US��|���4�'��Q��f������N��/�u�QC �    9]"�������0�c�'����X���U���[u݀A6I���+�SB9r�@�N�Z�ohiU��.�7.�    ~�\���x��,f��������a����,��A�����ZO����N(����Ĝ��ki��m�׵��������]\�ٶ�ˡu���H{C��F��z�p���pV��������g������_|�M?���w�/PK��q�P��"�PK����}�S�docProps/core.xml���N�0�E�%�>���TV��A]Q � �;�~m-�A�!�SX����Nhø@��������r�Wm���K�+�g�%���Ro+tӬ��J|`Z��h��6hY��Rn�\9c��   >���)��څ`)ƞ�@1�E����8�B<�-��?�-���9V��`����ڑ��H�G�}t���C�
t�8�r��hv   �^��(j@�E����g��g^�D�q�����\���oE0�a��6x�Q�C���j��G�h��]-������M�d|�3\ù�v�����:���[��0��n:5Dm
�[5�X��*    ;�u_[w��A�]m2(�|�i?c{�1�gܟgD�����`pA�=1h���h��J���L�y�=�).��VT�+\O�,݅���s����l�꩔�4��������j��V��PK��()�����PK�����}�S{<�$����_rels/.relsPK�����}�SG��R�
��*�[Content_Types].xmlPK�����}�S�q�P��"����docProps/app.xmlPK�����}�SU�~�7�3����docProps/core.xmlPK�����}�S�E6��������docProps/custom.xmlPK�����}�S7l]��������xl/sharedStrings.xmlPK�����}�S�g�OYwO
.   xl/styles.xmlPK�����}�Se4��������xl/theme/theme1.xmlPK�����}�S�a!p�������xl/workbook.xmlPK�����}�S���!����h�xl/_rels/workbook.xml.relsPK�����}�S�()��������xl/worksheets/sheet1.xmlPK������Y�
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容