后端接口返回文件流,前端实现docx/pdf/excel等类型文件的下载功能
最近遇到一个需求,在后端返回文件流后前端需要实现导出docx类型的文件。在网上查看了一些资料总结了两种比较常用的方法。

(图片来源网络,侵删)
方法一:前端接收到后端返回的数据后将返回结果转换为Blob类型,再进行操作。
1、封装接口
注意:接口需要添加 responseType: “blob”,否则会出现文件下载后无法打开或者损坏的情况。
export function downloadFile(id) { return request({ url: "/project/approval/getWord/" + id, responseType: "blob", method: "post", }) }
2、转换数据格式
导出word文件,需要在创建blob对象时传入第二个参数,并将type设置为“application/vnd.openxmlformats-officedocument.wordprocessingml.document”

(图片来源网络,侵删)
handleDownload() { downloadPromise(this.ids[0]).then((res) => { let blob = new Blob([res], { type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", }); let objectUrl = URL.createObjectURL(blob); let link = document.createElement("a"); let fname = "文件名称"; link.href = objectUrl; link.setAttribute("download", fname); document.body.appendChild(link); link.click(); }) .catch(() => { this.$modal.msgWarning("文件下载出错!"); }); },
方法二:封装download方法(修改若依前端导出文件方法)
1、封装download方法
//该方法需要接受四个参数url:后端请求地址,params:请求参数,filename文件名称,contentType:content-type类型。 export function download(url, params, filename, config, contentType) { downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", }) return service.post(url, params, { transformRequest: [(params) => { return tansParams(params) }], //这里可以根据导出文件的类型来传相应的Content-Type值 headers: { 'Content-Type': contentType ? contentType : 'application/x-www-form-urlencoded' }, responseType: 'blob', ...config }).then(async (data) => { const isBlob = blobValidate(data); if (isBlob) { const blob = new Blob([data]) saveAs(blob, filename) } else { const resText = await data.text(); const rspObj = JSON.parse(resText); const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'] Message.error(errMsg); } downloadLoadingInstance.close(); }).catch((r) => { console.error(r) Message.error('下载文件出现错误,请联系管理员!') downloadLoadingInstance.close(); }) }
2、调用download方法
handleDownload() { this.download( "/project/approval/getWord/" + this.ids[0], //没有请求参数则传空对象 {}, //文件名称可以自行设置 `type_${new Date().getTime()}.docx`, "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ); },
相关资料
在网上查找了一些关于 content-type 的编码格式以及responseType。
.doc application/msword .docx application/vnd.openxmlformats-officedocument.wordprocessingml.document .rtf application/rtf .xls application/vnd.ms-excel application/x-excel .xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet .ppt application/vnd.ms-powerpoint .pptx application/vnd.openxmlformats-officedocument.presentationml.presentation .pps application/vnd.ms-powerpoint .ppsx application/vnd.openxmlformats-officedocument.presentationml.slideshow .pdf application/pdf .swf application/x-shockwave-flash .dll application/x-msdownload .exe application/octet-stream .msi application/octet-stream .chm application/octet-stream .cab application/octet-stream .ocx application/octet-stream .rar application/octet-stream .tar application/x-tar .tgz application/x-compressed .zip application/x-zip-compressed .z application/x-compress .wav audio/wav .wma audio/x-ms-wma .wmv video/x-ms-wmv .mp3 .mp2 .mpe .mpeg .mpg audio/mpeg .rm application/vnd.rn-realmedia .mid .midi .rmi audio/mid .bmp image/bmp .gif image/gif .png image/png .tif .tiff image/tiff .jpe .jpeg .jpg image/jpeg .txt text/plain .xml text/xml .html text/html .css text/css .js text/javascript .mht .mhtml message/rfc822
"" responseType 设为空字符串与设置为"text"相同,默认类型 "text" 返回的是包含在 DOMString 对象中的文本。 "document" 返回的是一个 HTML Document 或 XML XMLDocument "arraybuffer" 返回的是一个包含二进制数据的 JavaScript ArrayBuffer "blob" 返回的是一个包含二进制数据的 Blob 对象 "json" 返回的是一个 JavaScript 对象 。这个对象是通过将接收到的数据类型视为 JSON 解析得到的。 "ms-stream" 返回的是下载流的一部分 ;此响应类型仅允许下载请求,并且仅受Internet Explorer支持
总结
使用第一种方法时遇到的坑,没有在接口api设置responseType: “blob”,导致文件下载成功后无法打开。最后,在前端开发过程中经常会遇到文件导出的需求,在这里总结一下用到过的方法以便在下次使用时可以直接复用。