前端开发中,导入和导出文件是比较常见的业务场景,常见的情况是:后端返回一个二进制的流文件,前端将其转化为excel文件即可。但是往往会出现转化后的excel文件内容位乱码的情况,本文中提供了两个解决方案:
方案一:用户自定义上传方法
<el-upload
:on-error="uploadError"
:accept="accept"
class="uploadContent"
:action="uploadurl"
:on-remove="handleRemove"
:before-remove="beforeRemove"
multiple
:limit="limit"
ref="uploadComponent"
:on-exceed="handleExceed"
:auto-upload="autoupload"
:file-list="fileList"
:data="uploadData"
:on-change="fileStateChange"
:http-request="handleupload"
>
<span v-if="showtip">添加附件</span>
<el-button class="btnColor2" size="small" type="primary">添加附件 </el-button>
</el-upload>
代码解读:上述代码采用了element-ui的el-upload文件上传的组件。改组件有两种文件上传的方式:
1.组件自带的上传方法,只需要给其设置action地址参数,即可完成上传,但是其弊端为无法在改组件的基础上设置后端相应的数据格式:responseType,或者是拿到后端响应的二进制流后将其转换为blob对象并为其设置responseType:'blob'无效的问题,从而导致导出的excl文件打开后为乱码的问题。
2.:http-request自定义上传方法。改方法也是本次主要的上传方法,此处使用自定义方法上传的有点便是可自定义上传接口的参数,上代码:
定义接口:
// 文件上传
export const userNameListUpload = (data, uploadurl) => axios.request({
url: uploadurl,
baseURL,
data,
method: 'post',
contentType: 'application/json;charset=UTF-8',
responseType: 'blob',
});
上述代码引用接口:userNameListUpload,在该接口的axios部分需要设置一下参数:
contentType: 'application/json;charset=UTF-8',
responseType: 'blob',
其含义是指定后端相应的数据类型为blob类型。
:http-request自定义上传函数:
async handleupload(option) {
const formData = new FormData();
if (option.data) {
Object.keys(option.data).forEach((key) => {
formData.append(key, option.data[key]);
});
}
formData.append(option.filename, option.file, option.file.name);
const loading = this.$loading({ text: '上传中...' });
const res = await userNameListUpload(formData, this.uploadurl);
loading.close();
if (res) {
this.$emit('uploadComplete', res); // 展示导入结果
}
},
前端在拿到后盾响应的数据后,只需将其转换为Blob对象,然后再以a标签的形式进行访问即可,上代码:
// 展示失败明细
falidDetail() {
// 有Success的直接展示
if (this.sendResponse.Success) {
if (this.sendResponse.Success) {
this.$message.success(this.sendResponse.Msg);
} else {
this.$message.error(this.sendResponse.Msg);
}
} else {
//=========================进行流转换为excel表格的操作,并导出excel===============
// 没有Success的直接展示ecxel表格
const blob = new Blob([this.sendResponse]);
const link = document.createElement('a');
link.style.display = 'none';
// setAttribute() 方法添加指定的属性,并为其赋指定的值。
link.setAttribute('download', '错误信息.xlsx');
link.href = window.URL.createObjectURL(blob);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(blob);
}
},
进行了这些设置后,即可正常导出excel文件了。
方案二:直接设置el-upload组件的headers树属性
el-upload组件提供了一个headers属性,可设置上传的请求头部::headers="headers"
<el-upload
:on-error="uploadError"
:accept="accept"
class="uploadContent"
:headers="header"
:action="uploadurl"
:on-remove="handleRemove"
:before-remove="beforeRemove"
multiple
:limit="limit"
ref="uploadComponent"
:on-exceed="handleExceed"
:auto-upload="autoupload"
:file-list="fileList"
:data="uploadData"
:on-change="fileStateChange"
:http-request="handleupload"
>
<span v-if="showtip">添加附件</span>
<el-button class="btnColor2" size="small" type="primary">添加附件 </el-button>
</el-upload>
给组件绑定一个headers属性,其值为对象header,属性值:responseType: 'blob'即可。
data(){
return {
header: { responseType: 'blob' },
};
}