需求:上传excel表格到服务器,然后接收返回的结果(二进制)并转成excel表格下载
实施:采用 Element-UI的uploade 组件,功能较全且有完整的生命周期钩子可设置。
<el-upload
class="upload-demo"
ref="upload"
action=""
:on-remove="handleRemove"
:on-error="handleError"
:file-list="fileList"
:auto-upload="false"
:limit=1
>
<el-button
slot="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 为 blob
xhr.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;
}