前言

台风天在家回顾一文件下载和上传功能的实现!

文件下载

点击按钮下载一个文件,一个出现频率极高的业务场景。
我们需要设置response Header中responseType,告诉后端我们需要的数据类型

export const getCartTemplate = () =>
  defHttp.get({
    url: Api.api_get_cart_template,
    // 确保获取类型正确的数据
    responseType: 'blob',
    headers: {
      ignoreCancelToken: true,
    },
  });

获取数据后,创建a标签进行自动点击:

// 这里的res即返回数据
 const saveFile = (res) => {
       let blob = new Blob([res], {
         // 为了保证浏览器能正确的解析Blob URL返回的文件类型,需要在创建Blob对象时指定相应的type  这里指定为.xlsx
         type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8',
       });
       // 创建一个临时的url指向blob对象
       let url = window.URL.createObjectURL(blob);
       let a = document.createElement('a');
       a.href = url;
       // 自定义文件名
       a.download = fileName.value;
       a.click();
       // 释放这个临时的对象url
       window.URL.revokeObjectURL(url);
     };

关于Blob对象:
Blob(blobParts[, options])

  • blobParts: 数组类型, 数组中的每一项连接起来构成Blob对象的数据,数组中的每项元素可以是ArrayBuffer(二进制数据缓冲区), ArrayBufferView,Blob,DOMString。或其他类似对象的混合体。
  • options: 可选项,字典格式类型,可以指定如下两个属性:
    type,默认值为"",它代表了将会被放入到blob中的数组内容的MIME类型。
    endings, 默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。 它是以下两个值中的一个: “native”,表示行结束符会被更改为适合宿主操作系统文件系统的换行符; “transparent”,表示会保持blob中保存的结束符不变。

type类型参考:

ExtMIME Type
.docapplication/msword
.dotapplication/msword
.docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.document
.dotxapplication/vnd.openxmlformats-officedocument.wordprocessingml.template
.docmapplication/vnd.ms-word.document.macroEnabled.12
.dotmapplication/vnd.ms-word.template.macroEnabled.12
.xlsapplication/vnd.ms-excel
.xltapplication/vnd.ms-excel
.xlaapplication/vnd.ms-excel
.xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet
.xltxapplication/vnd.openxmlformats-officedocument.spreadsheetml.template
.xlsmapplication/vnd.ms-excel.sheet.macroEnabled.12
.xltmapplication/vnd.ms-excel.template.macroEnabled.12
.xlamapplication/vnd.ms-excel.addin.macroEnabled.12
.xlsbapplication/vnd.ms-excel.sheet.binary.macroEnabled.12
.pptapplication/vnd.ms-powerpoint
.potapplication/vnd.ms-powerpoint
.ppsapplication/vnd.ms-powerpoint
.ppaapplication/vnd.ms-powerpoint
.pptxapplication/vnd.openxmlformats-officedocument.presentationml.presentation
.potxapplication/vnd.openxmlformats-officedocument.presentationml.template
.ppsxapplication/vnd.openxmlformats-officedocument.presentationml.slideshow
.ppamapplication/vnd.ms-powerpoint.addin.macroEnabled.12
.pptmapplication/vnd.ms-powerpoint.presentation.macroEnabled.12
.potmapplication/vnd.ms-powerpoint.presentation.macroEnabled.12
.ppsmapplication/vnd.ms-powerpoint.slideshow.macroEnabled.12
文件上传(基于ant-design-vue)

在点击按钮后上传文件,携带文件密码,密码可以为空!
模板部分:

<a-upload
        name="file"
        accept=".xls,.xlsx"
        :file-list="fileList"
        :showUploadList="true"
        :withCredentials="true"
        :headers="headers"
        :before-upload="beforeUpload"
        :disabled="loading"
        :remove="handleRemove"
      >
        <a-button>
          <SvgIcon name="upload" v-show="!loading" />
          {{ title }}
        </a-button>
 </a-upload>

其实就是手动上传,在antd的文档中已有示例: ant-design-vue upload组件.
简单描述就是需要在自动上传的基础上,添加两个参数:

参数说明
beforeUpload上传文件之前的钩子,参数为上传的文件,若返回 false 则停止上传。支持返回一个 Promise 对象,Promise 对象 reject 时则停止上传,resolve 时开始上传( resolve 传入 File 或 Blob 对象则上传 resolve 传入对象)。注意:IE9 不支持该方法。(file, fileList) => boolean |Promise
fileList已经上传的文件列表(受控)object[ ]

在beforeLoad中存储用户上传的文件,此时还没有真正上传:

      // 上传前
      const beforeUpload = (file: FileItem) => {
        console.log(file, ' file ');
        fileList.value = [file];
        return false;
      };

点击上传时:

	  const loading = ref(false);
      // 上传
      const handleUpload = async () => {
        if (!fileList.value.length) {
          message.error('Please upload first');
          return;
        }
        // 使用formData格式传递参数
        const fd = new FormData();
        fd.append('file', fileList.value[0]);
        fd.append('pwd', pwd.value);

        loading.value = true;

        try {
          // 发送请求
          const res = await importCart(fd);
          if (res.success) {
            // success
          } else {
         	// fail
        } catch (err) {
          console.log(err);
        } finally {
          loading.value = false;
        }
      };

之前由自动改为手动时,模仿了antd的content-type参数,去掉后发现并无影响:

export const importCart = (params) =>
  defHttp.post({
    url: Api.api_import_cart,
    params,
    // 使用antd自动上传时的 response header
    'Content-Type': 'application/octet-stream',
    headers: {
      ignoreCancelToken: true,
       // 使用antd自动上传时的 request header
      'Content-Type': 'multipart/form-data',
    },
  });

以上!

Logo

前往低代码交流专区

更多推荐