总结

上传文件碰到了三个问题,经过一番周折,总算解决了,这里记录下问题的原因和解决方式。

目录

目录

  • 总结
  • 目录
  • 项目功能
  • 问题
  • 解决方式

项目功能

  1. 上传excel【xls,xlsx】
  2. 后端返回文件流,前端进行数据处理并下载为xlsx

上传文件碰到了四个问题,经过一番周折,总算解决了,这里记录下问题的原因和解决方式。

问题

  • element的内置的上传文件方法与后端要求的方式不一致
  • 下载无法打开问题
  • 要求的excel上传后,后端进行批量注册的业务逻辑,返回给前端excel是否注册成功。在拿到后端的文件流中,有中文字符乱码。
  • 默认的文件名是随机产生的,如果使用自带的请求头时间格式要进行数据处理且后端返回的时间存在异常。

解决方式

解决第一个问题,element默认是使用action来指定URL提交的,而实际需求复杂的多。我们指定方法去实现文件的上传,在上传文件后服务端返回一个excel文件。下载成功后碰到文件无法打开问题

找到问题原因

xls使用的属性为application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

xlsx使用的属性为application/vnd.ms-excel

这里使用application/vnd.ms-excel;属性。

文件打开不报错了,打开.xlsx却遇到返回的数据为

显然,中文字符乱码了。排除content-type的问题

找到具体的原因出在未指定响应responseType的数据类型

这里我们添加上arrayBuffer属性。即responseType: 'arraybuffer',将数据存入数组中,这样就解决了返回数据的乱码问题。

默认的文件名是随机产生的,如果使用自带的请求头时间格式要进行数据处理且后端返回的时间存在异常。这里前端生成时间戳,转换成 yyyy-MM-dd HH:mm:ss返回给文件名。

这样以上问题基本上解决了,下面贴上具体的代码。

<el-upload
           class="upload-demo"
           drag
           accept=".xls, .xlsx"
           action="#"
           :before-upload="beforeAvatarUpload"
           :http-request="getfileUpload"
           :on-change="getValChange"
           :file-list="fileList"
           style="margin-left: 20px">
    <i class="el-icon-upload"></i>
    <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
    <div class="el-upload__tip" slot="tip">
        <el-button type="text" icon="el-icon-document" @click="download">还未下载模板?点击此处下载</el-button>
    </div>

</el-upload>
// 上传触发前 对文件格式的校验只校验了excel文件
beforeAvatarUpload(file) {
    let FileExt = file.name.replace(/.+\./, "").toLowerCase();
    let flag = ["xls", "xlsx"].includes(FileExt);
    if (!flag) this.$message.error("只能上传excel文件!");
    return flag;
},
// 文件值改变时触发 change事件
getValChange(file, fileList) {
    if (fileList.length > 0) {
        this.fileList = [fileList[fileList.length - 1]]
    } else {
        this.fileList = fileList[0]
    }
},
fileUpload(data) {
    let url = `/admin/batch-save`;
    return this.$http.post(url, data, {
        headers: {
            'Accept': 'application/json;charset=UTF-8',
            'Content-Type': 'multipart/form-data;'
        },
        responseType: 'arraybuffer'
    })
},
// 时间戳处理
function formatDate() {
    var date = new Date();
    var YY = date.getFullYear() + '-';
    var MM = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
    var DD = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate());
    var hh = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
    var mm = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) + ':';
    var ss = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
    return YY + MM + DD +" "+hh + mm + ss;
}
// 上传调用后台接口
getfileUpload() {
    let formData = new FormData();
    formData.append("batchFile", this.fileList[0].raw);
    this.fileUpload(formData).then((response) => {
        this.$message.success("上传成功!");
        const pdfUrl = window.URL.createObjectURL(new Blob([response.data], { type: `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet` }));
        const link = document.createElement('a');
        link.href = pdfUrl;
        link.setAttribute('download',formatDate());
        document.body.appendChild(link);
        link.click();
    });
},