前端开发中,经常遇到文件下载的功能。这里对常见的文件下载方式做一些总结。
前端下载通常分为两种情形,一种是后端直接给一个文件地址,通过浏览器打开就可以下载,另外一种则需要发送请求,后端返回二进制流数据,前端解析流数据,生成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地址的文件只能预览,那么这种文件要下载的解决方式:
- 改为请求接口得到流的方式下载(可能面临大文件时接口请求时间非常长的问题)
- 直接访问文件地址,在地址后添加参数 ?response-content-type=application%2Foctet-stream
例如:https://XXX.XX.XXX:5443/alibaba/16583705678118fad71ee6fad4bcfb91a9cafb8335800.mp4?response-content-type=application%2Foctet-stream
举个例子:
在阿里云 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);
后台返回的二进制数据文件流格式如图:
参考这个样子
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�