前端实现导入导出zip(解决火狐浏览器下载没带后缀bug)

前端框架 vue + antvue + ts + axios
场景: 实现导出zip包到本地,导出的zip包可以再编辑后导入系统

导出功能

将数据流转成zip下载到本地

功能实现

使用a标签的下载功能。
download可以设置下载文件的名称
注意当使用download属性实现下载时要添加后缀!!!
遇到的小坑:
1.download的兼容性不好,火狐ie之类的不会自动添加上后缀,在名称后面追加.zip既可解决该兼容问题,并且在谷歌等正常浏览器中也不会重复
2.名称如果是特殊字符谷歌浏览器也不会自动拼上后缀
如果这里文件名有带时间戳一定要排除空格,带空格的文件名火狐浏览器也会识别不了后缀!!!

 async handleExport() {
    this.exportLoading = true  // 触发接口前loading
    const res = await service.getExportApp(this.appData.id)
    this.exportLoading = false // 接口响应完结束loading
    const blob = new Blob([res], { type: 'application/zip' })   // 指定格式
    const link = document.createElement('a'); 
    link.href = URL.createObjectURL(blob);
    link.download = `${this.appData.label}.zip` ;  // 指定导出名称
    link.click();
    URL.revokeObjectURL(link.href);
    this.$message.success('应用导出成功')
  }

设置请求头,后台返回数据流类型前端一定要设置responseType
没设置responseType导出到本地的zip是解压不出来的(改成txt后缀就 可以打开里面只有一个false)

/**
 * 导出应用
 * @param id 应用id
 */
export const getExportApp = (id) => {
  const params: object = {
    headers: {
      'Content-Type': 'application/json; charset=utf-8'
    },
    responseType: 'blob' // 表明返回服务器返回的数据类型
  }
  return axios.get(`/export/${id}`, params)
};

导入功能

使用了ant-vue 的upload组件,后台需要的参数是文件流,需要用new FormData();
beforeUpload 方法返回false来阻止默认上传行为(没返回false的话会触发默认的action行为,就算没设置action也会请求一个空的接口)
使用customRequest 通过覆盖默认的上传行为,自定义自己的上传实现

// 模板
<a-upload-dragger
     name="file"
     accept=".zip"
     :show-upload-list="false"
     :before-upload="beforeUpload"
     @customRequest="handleUpload"
 >
   <p class="ant-upload-drag-icon">
          <a-icon type="upload" />
    </p>
    <p class="ant-upload-text">
            点击拖拽上传
    </p>

</a-upload-dragger>

js 实现

// 上传之前
  beforeUpload(file: any) {
    this.handleUpload(file);
    return false;
  }
  // 自定义上传方法(校验可以放这儿)
  handleUpload(file: any) {
    console.log('beforeUpload')
    const ext: string = file.name.split('.').pop();
    if (!this.checkFileType(ext)) {
      this.$message.warning(`不支持 ${ext} 格式的图片!`);
    } else {
      this.upload(file)
    }
  }
  // 上传
  async upload(file: any) {
    const formData = new FormData();
    console.log(file)
    formData.append('file', file);  // 转换成文件流
    const { code, data } = await service.putImportApp(formData)
    if (code === 0) this.success = true
  }

导入导出的请求头跟默认的请求头不一致,都需要重新设置
使用form-data 可传输大型二进制数据或者包含非ASCII字符的数据

/**
 * 导入应用
 * @param params 需要导入的文件 file : Zip
 */
export const putImportApp = (query) => {
  const params: object = {
    headers: {
      'Content-Type': 'multipart/form-data' 
    },
  }
  return axios.put(`/import`, query, params)
};
posted @ 2021-11-18 18:08  whkl梅  阅读(1328)  评论(0编辑  收藏  举报