文件上传与下载的封装

400 阅读2分钟

在我们的日常开发中,文件上传与下载一直都是比较常见的问题,为了统一开发者的书写和保障开发效率,这里对文件的上传下载做了如下封装

axios封装

import axios from "axios";
import { Message } from "element-ui";
const request = axios;

request.interceptors.request.use(
  function (config) {
    if (store.state.userInfo.access_token) {
      config.headers["access_token"] = getToken();
    }
    return config;
  },
  function (error) {
    return Promise.reject(error);
  }
);

request.interceptors.response.use(
  function (response) {
    //文件下载处理
    const headers = response.headers;
     if (headers["content-type"] === "application/octet-stream") {
    if (headers["content-disposition"]) {
      sessionStorage.setItem(
        "content-disposition",
        headers["content-disposition"]
      );
       }
      return response.data;
    }
    // 对响应数据做点什么
    let data = response.data;
    let { message, code } = data;
    if (code !== 200) {
      Message.error({
        message: "系统异常",
      });
      return Promise.reject(response.data || "Error");
    }
 
    return data;
  },
  function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  }
);

export default request;

封装上传下载api

import request from "@/plugins/axios/request.js";

// 全局上传的请求函数(请不要操作)
export function upload(data, url, method = "post") {
  return request({
    url: url,
    method: method,
    data,
    headers: { "Content-Type": "multipart/form-data" },
  });
}

// 下载文件以流的形式
export function downloadStream(data, url, method = "get", isBlob = true) {
  // 该列表中 url responseType 不为 blob
  const urlWhiteList = [];
  if (urlWhiteList.includes(url)) {
    isBlob = false;
  }
  const temp = {
    url: url,
  };
  if (isBlob) {
    temp.responseType = "blob";
  }
  if (method === "post") {
    temp.method = "post";
    temp.data = data;
  } else {
    temp.method = "get";
    temp.params = data;
  }
  return request(temp);
}

// 删除文件
export function deleteFile(data, url, method = "post") {
  if (method === "post") {
    return request({
      url: url,
      method: method,
      data,
    });
  } else {
    return request({
      url: url,
      method: method,
      params: data,
    });
  }
}

封装下载公共方法

/**
 * @description: 以流的形式下载文件
 * @param: {Blob} 流文件
 * @return {undefined}
 * @author: zzl
 */
export function downloadFile(res, type = "pdf") {
  if (res.data) {
    const url = pathJoin(process.env.VUE_APP_BASE_API, res.data);
    downloadForA(url);
  } else {
    // 兼容 ie
    if (checkBrowser().includes("IE")) {
      const blob = new Blob([res]);
      window.navigator.msSaveOrOpenBlob(blob, `${res.fileName}.${type}`);
    } else {
      const blobUrl = window.URL.createObjectURL(new Blob([res]));
      downloadForA(blobUrl);
    }
  }
}

function downloadForA(url) {
  let temp =
    sessionStorage.getItem("content-disposition") &&
    sessionStorage.getItem("content-disposition").split("=");
  temp = temp && temp[temp.length - 1];
  // 进行解码获取文件名称
  let fileName = decodeURI(temp);
  const fileNameSplit = fileName.split(".");
  if (fileNameSplit.length === 2 && fileNameSplit[0] === "") {
    fileName = "file" + fileName;
  }
  const link = document.createElement("a");
  link.style.display = "none";
  link.href = url;
  link.setAttribute("download", fileName);
  // 模拟
  document.body.appendChild(link);
  link.click();
  // 释放URL 对象
  window.URL.revokeObjectURL(link.href);
  document.body.removeChild(link);
}

前端具体使用

上传文件

import { upload } from "@/api/fileApi/index.js";

  // 上传安装包
    uploadFile(param) {
      const formData = new FormData();
      //表单可以添加文件和很多字段
      formData.append("file", param.file);
      formData.append("softwareId", this.currentId);
      upload(
        formData,
        "你的接口地址",
        "post"
      )
        .then((res) => {
          const { code, data, message } = res;
          if (code === 200) {
            this.$message.success("上传成功");
          }
        })
        .catch(() => {
          this.$message.warning("上传失败");
        });
    },

下载文件

import {  downloadStream } from "@/api/fileApi/index.js";
import { downloadFile } from "@/plugins/axios/fileHalder.js";
    // 下载安装包 这里downloadStrea api和downloadFile公共方法结合使用
    downloadPackage(id) {
      downloadStream(
        { softwareId: id },
        "你的下载地址",
        "get"
      ).then((res) => {
        downloadFile(res);
      });
    },

后端

后端以流的形式输出文件,

response.setHeader("content-type","application/octet-stream")
response.setHeader("content-disposition",fileName) //注意这里的文件名要UTF-8编码
response.outPutStream(fileStream) //输出文件流
response.outPutStream.close() //关闭流