前端实现下载文件(包含压缩包下载)方式详细总结

 更新时间:2023年09月10日 14:55:53   作者:qq_38969618  
这篇文章主要给大家介绍了关于前端实现下载文件(包含压缩包下载)方式的相关资料,这段时间项目需要下载文件,所以这里给大家总结下,需要的朋友可以参考下

前言

默认最简单的下载方式是:window.open(后台接口API路径),但该方法弊端:因是新开窗口方式,前端展示上,每次会闪下。

此外,如果使用window.open(文件URL)方式:

  • pdf、office文档、psd:直接下载。
  • 图片、txt:新开窗口预览,不会下载;且txt预览,有时出现中文乱码问题。

一、根据文件URL下载

实现原理:通过a标签实现下载。

/**
 * @method 下载单个文件(文件类型可任意:.png、txt、office文档、.psd等)
 * @param { String } url - 文件的http完整路径, 如:http: //xxx.png
 * @param { String } fileName - 文件名,注意是要带文件后缀名,如:xxx.png
 * @doc https://blog.csdn.net/weixin_39547158/article/details/110851570
 */
export function downloadFile(url: string, fileName: string) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'blob';
    xhr.upload.onprogress = (e) => {
      if (e.lengthComputable) {
        let progress = e.loaded / e.total;
        console.log('文件上传进度是', progress);
      }
    };
    xhr.onload = function () {
      const url = window.URL.createObjectURL(xhr.response);
      const eleLink = document.createElement('a');
      eleLink.href = url;
      eleLink.download = `${fileName}`;
      eleLink.style.display = 'none';
      document.body.appendChild(eleLink);
      eleLink.click();
      document.body.removeChild(eleLink);
      resolve('success');
    };
    xhr.onerror = (e) => {
      console.log('请求错误回调', e);
      message.warning('下载文件失败')
      reject(e);
    };
    xhr.send();
  });
}

二、excel文件:调用后台接口返回文件流,前端下载文件

实现原理:调用后台接口,返回blob, 前端使用file-saver库实现下载。

// 下载excel文件
import { saveAs } from 'file-saver';
const downloadTemplate = async () => {
  try {
    const params = { ... } // 传参
    const res = await generateDownStreamReconciliationUsingGET(params);
    // res为返回结果
    if (res) {
      const blob = new Blob([res], { type: 'application/vnd.ms-excel' });
      FileSaver.saveAs(blob, '对账单.xlsx');
      console.log('对账单下载成功')
    }
  } catch (e) {
    console.log(e);
  } finally {
    console.log('finally')
  }
};
// 生成对账excel模板表格API
export async function generateDownStreamReconciliationUsingGET(
  params: API.generateDownStreamReconciliationUsingGETParams,
  options?: { [key: string]: any },
) {
  return request<any>(
    `${process.env.APP_HOST_WAYBILL}/xxx/generateDownStreamReconciliation`,
    {
      method: 'GET',
      responseType: 'blob',  // 必须写该行,否则:后台返回的是string,不是blob且文件下载后,会出现打不开问题。
      params: {
        ...params,
      },
      ...(options || {}),
    },
  );
}

三、多文件URL下载,前端生成压缩包下载

实现原理:jszip库 + file-saver库

import { getBlobOfUrl } from '@/services/common';
import { saveAs } from 'file-saver';
import JSZip from 'jszip';
import { message } from 'antd';
/**
 * @method 同时下载多文件,并生成一个压缩包
 * @param { Object[] } fileInfoList - 文件列表
 * @param { String } urlField - 文件URL的字段名
 * @param { String } fileNameField - 文件名的字段名
 * @param { String } folderName - 压缩包 & 文件夹名称
 */
export function downloadAsZip(
  fileInfoList: any[],
  folderName = '文件压缩包',
  urlField = 'filePath',
  fileNameField = 'name',
) {
  return new Promise((resolve, reject) => {
    const zip = new JSZip();
    // const folder = zip.folder(folderName); // 创建文件夹
    const promisesList = fileInfoList.map((item) => {
      return getBlobOfUrl(item[urlField])
        .then((data) => {
          // console.log(data); // Blob
          // folder.file(item[fileNameField], data, { binary: true }); // 往文件夹中存放文件
          zip.file(item[fileNameField], data, { binary: true }); // 不创建文件夹
        })
        .catch((e) => {
          console.log(e);
          message.warning(e?.message || '获取文件流失败')
        });
    });
    Promise.all(promisesList)
      .then(() => {
        zip
          .generateAsync({ type: 'blob' })
          .then((content) => {
            saveAs(content, folderName);
            resolve('success');
          })
          .catch((e) => {
            message.warning(e?.message || '生成压缩包失败')
            reject(e);
          });
      })
      .catch((e) => {
        message.warning(e?.message || '批量获取文件流失败')
        reject(e);
      });
  });
}
import { request } from 'umi';
/**
 * @method 根据文件URL获取blob数据流的API
 * @param { String } fileUrl - 文件完整路径,如:http://xxx.png
 */
export function getBlobOfUrl(fileUrl: string) {
  return request(fileUrl, {
    method: 'GET',
    responseType: 'blob', // 设置后台返回的内容类型为blob
    params: {
      notAuthorization: true,
    },
  });
}

总结 

到此这篇关于前端实现下载文件(包含压缩包下载)方式的文章就介绍到这了,更多相关前端实现下载文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • javascript内置对象Math案例总结分析

    javascript内置对象Math案例总结分析

    今天总结一下javascript 内置对象Math中的函数用法,顺带写一下常见的案例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-03-03
  • 微信小程序自定义tabBar在uni-app的适配详解

    微信小程序自定义tabBar在uni-app的适配详解

    这篇文章主要介绍了微信小程序自定义tabBar在uni-app的适配详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • 使用uni-app开发微信小程序的实现

    使用uni-app开发微信小程序的实现

    这篇文章主要介绍了使用uni-app开发微信小程序的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • BootStrap入门教程(一)之可视化布局

    BootStrap入门教程(一)之可视化布局

    这篇文章主要介绍了bootstrap可视化布局入门教程的相关资料,本文介绍的非常详细,具有参考借鉴价值,感兴趣的朋友一起看看吧
    2016-09-09
  • 微信小程序iBeacon测距及稳定程序的实现解析

    微信小程序iBeacon测距及稳定程序的实现解析

    这篇文章主要介绍了微信小程序iBeacon测距及稳定程序的实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • JavaScript的public、private和privileged模式

    JavaScript的public、private和privileged模式

    公共/私有变量和方法通过一个简单的的例子,来展示如何使用JavaScript在类里面创建私有变量和方法
    2009-12-12
  • js鼠标滑轮滚动事件绑定的简单实例(兼容主流浏览器)

    js鼠标滑轮滚动事件绑定的简单实例(兼容主流浏览器)

    本篇文章主要介绍了js鼠标滑轮滚动事件绑定的简单实例(兼容主流浏览器)。需要的朋友可以过来参考下,希望对大家有所帮助
    2014-01-01
  • JS实现头条新闻的经典轮播图效果示例

    JS实现头条新闻的经典轮播图效果示例

    这篇文章主要介绍了JS实现头条新闻的经典轮播图效果,涉及javascript图片轮播切换相关实现技巧,需要的朋友可以参考下
    2019-01-01
  • Bootstrap企业网站实战项目4

    Bootstrap企业网站实战项目4

    这篇文章主要为大家分享了Bootstrap企业网站实战项目,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • ECMAScript6中Map映射的基本概念与常用方法

    ECMAScript6中Map映射的基本概念与常用方法

    Map是ES6中新增的数据结构,Map类似于对象,但普通对象的 key 必须是字符串或者数字,而 Map 的 key 可以是任何数据类型,这篇文章主要给大家介绍了关于ECMAScript6中Map映射的基本概念与常用方法,需要的朋友可以参考下
    2021-07-07

最新评论