前端,单个文件下载或者分批压缩多个文件下载

import JSZip from "jszip";
import fileSaver from "file-saver";
import axios from 'axios'
import {
  Message,
  Notification
} from "element-ui";


//下载单个文件
export const downloadSingleFile = (url, filename,postfix,blodFile) => {
  filename = filename || "文件名";
  let suffix =!postfix? /\.([0-9a-zA-Z]+)$/i.exec(url)[1]:postfix;
  const file_type = {
    'doc': 'application/msword',
    'bin': 'application/octet-stream',
    'exe': 'application/octet-stream',
    'so': 'application/octet-stream',
    'dll': 'application/octet-stream',
    'pdf': 'application/pdf',
    'ai': 'application/postscript',
    'xls': 'application/vnd.ms-excel',
    'ppt': 'application/vnd.ms-powerpoint',
    'dir': 'application/x-director',
    'js': 'application/x-javascript',
    'swf': 'application/x-shockwave-flash',
    'xhtml': 'application/xhtml+xml',
    'xht': 'application/xhtml+xml',
    'zip': 'application/zip',
    'mid': 'audio/midi',
    'midi': 'audio/midi',
    'mp3': 'audio/mpeg',
    'rm': 'audio/x-pn-realaudio',
    'rpm': 'audio/x-pn-realaudio-plugin',
    'wav': 'audio/x-wav',
    'bmp': 'image/bmp',
    'gif': 'image/gif',
    'jpeg': 'image/jpeg',
    'jpg': 'image/jpeg',
    'png': 'image/png',
    'css': 'text/css',
    'html': 'text/html',
    'htm': 'text/html',
    'txt': 'text/plain',
    'xsl': 'text/xml',
    'xml': 'text/xml',
    'mpeg': 'video/mpeg',
    'mpg': 'video/mpeg',
    'avi': 'video/x-msvideo',
    'movie': 'video/x-sgi-movie',
    'xlsx':"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
  }

  if (blodFile) {
    try {
      BlodTurnFile(blodFile,file_type[suffix],filename);
    } catch (error) {
      console.log(error,"文件流下载失败");
    }
    return
  }

  return new Promise((resolve, reject) => {
    console.log(url, "url");
    axios
      .get(url, {
        responseType: 'blob',
      })
      .then((res) => {
        // const blob = new Blob([res.data], {
        //   type: file_type[suffix]
        // }) // 构造一个blob对象来处理数据,并设置文件类型
        // if (window.navigator.msSaveOrOpenBlob) {
        //   // 兼容IE10
        //   navigator.msSaveBlob(blob, filename)
        // } else {
        //   const href = URL.createObjectURL(blob) // 创建新的URL表示指定的blob对象
        //   const a = document.createElement('a')
        //   a.style.display = 'none'
        //   a.href = href // 指定下载链接
        //   a.download = filename // 指定下载文件名
        //   a.click()
        //   URL.revokeObjectURL(a.href) // 释放URL对象
        //   a.remove();
        // }
        BlodTurnFile(res.data,file_type[suffix],filename);
        resolve("下载成功!")
      })
  })
}

/**
 * 二进制转文件
 * @param {*} blodStr 二进制流
 * @param {*} type 文件类型
 * @param {*} name 文件名称
 */
const BlodTurnFile=(blodStr,type,filename)=>{
  const blob = new Blob([blodStr], {
    type: type
  }) // 构造一个blob对象来处理数据,并设置文件类型
  if (window.navigator.msSaveOrOpenBlob) {
    // 兼容IE10
    navigator.msSaveBlob(blob, filename)
  } else {
    const href = URL.createObjectURL(blob) // 创建新的URL表示指定的blob对象
    const a = document.createElement('a')
    a.style.display = 'none'
    a.href = href // 指定下载链接
    a.download = filename // 指定下载文件名
    a.click()
    URL.revokeObjectURL(a.href) // 释放URL对象
    a.remove();
  }
}

let file_num = 0;
const zip = new JSZip();
let zip_obj = [];
let floder_obj = [];
let file_order = 0;
let file_floder = null;
let file_data = [];
let file_title = "";
let cur_title = "";
let breakpoint_num = 500; //断点数据
let allowZipFile = true; //等待压缩完成
/**
 * [链接数组]
 * @param  {[type]} paths [{"name":"初三排课班级课表","path":"https://liangcai-product-south.oss-cn-shenzhen.aliyuncs.com/newUpload/xls/初三排课班级课表_1589189955975.xls"}]
 * @return {[type]} 下载压缩文件 [description]
 */
export const downloadCompressedFiles = ({
  paths = [],
  title = "文件批量下载",
  percentCallback = () => {},
}) => {
  allowZipFile = true;
  file_order = 0;
  cur_title = (title && title) || "文件批量下载";
  file_title = paths.length > breakpoint_num ? title ? `${title}文件第1~${breakpoint_num}个` : `文件批量下载文件1~${breakpoint_num}个` : (title && title) || "文件批量下载";
  zip_obj[file_order] = new JSZip();
  floder_obj[file_order] = zip_obj[file_order].folder(file_title);
  // file_floder = zip.folder((title && title) || "文件批量下载");
  file_num = 0;

  if (paths.length) {
    file_data = paths;
    if (file_num < paths.length) {
      getUrlBlod(paths[file_num].path, paths[file_num].name, percentCallback);
    }
  }

}

const getUrlBlod = (url, name, percentCallback = () => {}) => {
  // 从url获取文件后缀
  let suffix = /\.([0-9a-zA-Z]+)$/i.exec(url)[1];
  let promise = httpPost({
    url
  }).then((data) => {
    console.log(file_order, "data123");
    // console.log(floder_obj[file_order]);
    floder_obj[file_order].file(`${name}.${suffix}`, data, {
      binary: true
    }); //逐个添加文件
    file_num = file_num + 1;
    if (file_num != file_data.length) {
      if (file_num % breakpoint_num == 0) {
        let _temp = file_order;
        file_order = file_order + 1;
        // file_title = (breakpoint_num + file_num) <= file_data.length ? `${cur_title}文件第${breakpoint_num*_temp}~${file_num}个` : `${cur_title}文件第${file_num}~${file_data.length}个`;
        file_title=`${cur_title}文件第${breakpoint_num*_temp}~${file_num}个`;
        zip_obj[file_order] = new JSZip();
        floder_obj[file_order] = zip_obj[file_order].folder((file_title && file_title) || "文件批量下载");
        Notification({
          title: '提示',
          message: file_title + '开始压缩文件中!请等待',
          type: 'info',
          duration: 0
        });
        allowZipFile = false;
        zipGenerateAsync(_temp, percentCallback);
      }
      percentCallback(file_num)
      if (allowZipFile) {
        getUrlBlod(file_data[file_num].path, file_data[file_num].name, percentCallback);
      }
    } else {
      if (file_num >= file_data.length) {
        file_title = `${cur_title}文件第${breakpoint_num * file_order}~${file_data.length}个`;
      }
      let _temp = file_order;
      Notification({
        title: '提示',
        message: file_title + '开始压缩文件中!请等待',
        type: 'info',
        duration: 0
      });
      allowZipFile = false;
      zipGenerateAsync(_temp, percentCallback);
    }
    return file_num;
  }).catch(err => {
    // console.log(err, "err123");
    // Message.error(`${name}文件下载失败!`);
    file_num = file_num + 1;
    if (file_num != file_data.length) {
      if (file_num % breakpoint_num == 0) {
        let _temp = file_order;
        file_order = file_order + 1;
        // file_title = (breakpoint_num + file_num) <= file_data.length ? `${cur_title}文件第${breakpoint_num*_temp}~${file_num}个` : `${cur_title}文件第${file_num}~${file_data.length}个`;
        file_title=`${cur_title}文件第${breakpoint_num*_temp}~${file_num}个`;
        zip_obj[file_order] = new JSZip();
        floder_obj[file_order] = zip_obj[file_order].folder(file_title);
        Notification({
          title: '提示',
          message: file_title + '开始压缩文件中!请等待',
          type: 'info',
          duration: 0
        });
        allowZipFile = false;
        zipGenerateAsync(_temp, percentCallback);
      }
      percentCallback(file_num)
      if (allowZipFile) {
        getUrlBlod(file_data[file_num].path, file_data[file_num].name, percentCallback);
      }

    } else {
      if (file_num >= file_data.length) {
        file_title = `${cur_title}文件第${breakpoint_num * file_order}~${file_data.length}个`;
      }
      Notification({
        title: '提示',
        message: file_title + '开始压缩文件中!请等待',
        type: 'info',
        duration: 0
      });
      let _temp = file_order;
      allowZipFile = false;
      zipGenerateAsync(_temp, percentCallback);
    }
  });

}

const zipGenerateAsync = (num, percentCallback = () => {}) => {
  zip_obj[num].generateAsync({
    type: "blob"
  }).then((content) => {

    Notification({
      title: '成功',
      message: file_title + '压缩文件下载成功',
      type: 'success',
      duration: 0
    });
    // 生成二进制流
    fileSaver.saveAs(
      content,
      (file_title && `${file_title}.zip`) || "文件批量下载.zip"
    ); // 利用file-saver保存文件
    // Message.error(`压缩文件下载成功!`);
    if (file_num == file_data.length) {
      file_num = file_num + 1;
    }

    percentCallback(file_num);
    zip_obj[num] = "";
    floder_obj[num] = "";
    if (file_num < file_data.length) {
      allowZipFile = true;
      getUrlBlod(file_data[file_num].path, file_data[file_num].name, percentCallback);
    }

    // Message({
    //   message: '压缩包文件下载成功!',
    //   type: 'success'
    // });
  }).catch(err => {
    console.log(err, "压缩下载失败");
    zip_obj[num] = "";
    floder_obj[num] = "";
    allowZipFile = true;
    getUrlBlod(file_data[file_num].path, file_data[file_num].name, percentCallback);
    Notification.error({
      title: '错误',
      message: file_title + '压缩下载失败',
      duration: 0
    });
  });
}

const getInPath = (url, name = "") => {
  return new Promise(async (resolve, reject) => {
    // let result = await axiosDownload(url);
    // if (result) {
    //   resolve(result.data);
    // } else {
    //   reject();
    // }
    await axiosDownload(url).then(res => {
      resolve(res.data)
    }).catch(err => {
      reject(err)
    })
  });
};

const axiosDownload = (url, resOpts = {}) => {
  const {
    type = "get", data = ""
  } = resOpts;
  const queryArgs = {
    url,
    method: type,
    data,
    responseType: "blob",
    // headers: {//这个地方看情况而定,如果打开会存在跨域问题
    //   Accept: "application/json",
    //   "Content-Type": "application/json; charset=utf-8",
    //   withCredentials: true,
    // },
  };
  // tips: 这里直接返回的是response整体!
  return new Promise((resolve, reject) =>
    axios
    .request(queryArgs)
    .then((res) => resolve(res))
    .catch((err) => reject(err))
  );
};



const axiosConfig = {
  // headers: {
  //   'Content-Type': 'application/json;charset=UTF-8',
  // },
  // timeout: 60000,
  responseType: 'blob',
}

const request = axios.create(axiosConfig);

let isRefreshing = false;
let queue = [];

let runQueue = () => {
  isRefreshing = true
  let first = queue.shift();
  first.request()
}

//请求拦截
//所有的网络请求都会先走这个方法
// 添加请求拦截器,所有的网络请求都会先走这个方法,我们可以在它里面为请求添加一些自定义的内容
request.interceptors.request.use((config) => {
  // 在发送请求之前做些什么
  return config;
}, function (error) {
  return Promise.reject(error);
});

// 添加响应拦截器
request.interceptors.response.use(function (response) {
  isRefreshing = false
  if (!(queue.length === 0)) runQueue()
  return response.data
}, function (error) {
  console.log(error, 2343);
  isRefreshing = false
  if (!(queue.length === 0)) runQueue()
  // 对响应错误做点什么
  return Promise.reject(error);
});

const httpPost = async ({
  url,
  method = 'get',
  data = "",
}) => {
  return new Promise((resolve, reject) => {
    queue.push({
      request: () => {
        request({
          method,
          url,
          data,
        }).then(res => {
          resolve(res)
        }).catch(e => {
          reject(e)
        })
      }
    })
    if (!isRefreshing) runQueue()
  })
}

 

posted @ 2022-02-14 14:02  春春&  阅读(487)  评论(0编辑  收藏  举报