需求:上传excel表格到服务器,然后接收返回的结果(二进制)并转成excel表格下载
实施:采用 Element-UI的uploade 组件,功能较全且有完整的生命周期钩子可设置。
<el-uploadclass="upload-demo"ref="upload"action="":on-remove="handleRemove":on-error="handleError":file-list="fileList":auto-upload="false":limit=1><el-buttonslot="trigger"size="small"type="primary">选取文件</el-button></el-upload>
问题1:post请求,不能用window.open(_url)的方式触发浏览器下载。
解决方法:在DOM中增加一个a标签,href设置成转出文件地址,手动触发a标签的click事件。
downloadFile(data) {if (!data) {return;}let url = window.URL.createObjectURL(new Blob([data]));let link = document.createElement("a");link.style.display = "none";link.href = url;link.setAttribute("download", "check.xlsx");document.body.appendChild(link);link.click();document.body.removeChild(link);}
ok,成功下载了.xlsx文件。
问题2:下载的.xlsx文件无法打开,office excel 提示文件被损坏
原因分析:Uploader组件包装了上传的文件/请求,导致返回的数据类型出现错误,无法转换成真正的.xlsx文件。
解决方法:
采用原生的Request对象发送请求,拿到返回的Response,再调用 downloadFile() 方法
var formData = new FormData();//FormData对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据formData.append("file", this.$refs.upload.uploadFiles[0].raw);//拿到组件中的上传文件的原始数据,添加到FormData中var xhr = new XMLHttpRequest();xhr.responseType = "blob";//设置responseType 为 blobxhr.open("POST","http://devserver.6tiantian.com/ajax/question-bank-service/admin/question/knowledge_tag/check",true);xhr.onload = function() {this.downloadFile(xhr.response);}.bind(this);xhr.send(formData); //发送请求},
问题3:由于设置responseType为blob,当后端报错时,无法直接显示报错信息。要将blob类型转成string。这里用到 fileReader 对象。
FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
解决方法:
xhr.onload = function() {if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {this.res = xhr.response;toastr.success("上传成功!");this.status = 2;} else {var fr = new FileReader();fr.onload = function(e) {toastr.error(e.target.result);};fr.readAsText(xhr.response);this.status = 0;}