前端批量获取文件并打包压缩解决方案

更新日期: 2021-06-08阅读: 1.6k标签: 文件

前言

前端文件下载我相信很多小伙伴并不陌生,下载文件的形式也有很多,例如,后端返回一个文件地址,我们把地址放在<a></a>标签里面点击下载;或者是通过后端接口返回文件流,我们再对流进行一系列的操作等等。

单个件下载的解决方法有很多,但是当我们需要批量下载文件的时候,我们该怎么去做呢?


方案

面对这样的需求,我们提出了以下几个方案:

方案一:直接获取后端返回文件地址数组,然后一个一个的去下载。但是这样每次下载一个文件,浏览器会显示比较多的下载任务;

方案二:后端对先对文件进行打包压缩处理,然后前端只需要下载一个压缩文件,但是这样会对服务器性能造成很大的影响;

方案三:还是直接获取后端返回的文件地址数组,一个一个的去下载,然后前端来进行打包压缩的处理。

说实话,当时提到前端来打包压缩时,我心中就和一部分小伙伴一样,前端怎么打包压缩?下面这两个优秀的库就可以很好的解决我们的问题。

这里提一下,下面是以react环境下为例,但是在其他环境的思路和用法其实都是大同小异,都可以以下面的内容为参考。


JSZip和FileSaver.js

本节会简单的介绍一下JSZip和FileSaver.js的api和用法。

安装

npm install jszip file-saver

JSZip

JSZip是一个用于创建、读取和编辑.zip文件的javascript库,并且拥有有友好而简单的API。

一个简单的例子

首先我们来实现一个简单的例子,来感受一下这个十分好用的工具

import React , { useState } from 'react';
import JSZip from 'jszip';
import FileSaver from 'file-saver'; 


const MyButton = () => {

    const downloadFile = () => {
        const zip = new JSZip();
        zip.file("Hello.txt", "Hello World\n");
        zip.generateAsync({type:"blob"})
        .then((content) => { 
            FileSaver(content, "example.zip");
        });
    }

    return (
        <div>
            <button onClick={() => {
                downloadFile()
            }}>下载</button>
        </div>
    )
} 

export default MyButton

点击下载按钮,我们就可以得到一个名为example.zip的压缩文件,打开压缩文件,里面也会有一个名为Hello.txt的文件.

API

简单介绍一下几个API。

创建JSZip实例:

const zip = new JSZip();

创建文件:

zip.file("hello.txt", "Hello World\n");

创建文件夹:

zip.folder("file")

同时创建文件夹和文件:

zip.file("file/hello.txt", "Hello World\n");
// 等同于
zip.folder("file").file("hello.txt", "Hello World\n");

生成一个压缩文件:

我们可以通过.generateAsync(options) 或者 .generateNodeStream(options) 来生成一个压缩文件:

let promise = null;
if (JSZip.support.uint8array) {
  promise = zip.generateAsync({type : "uint8array"});
} else {
  promise = zip.generateAsync({type : "string"});
}

详细API点击官方文档

FileSaver.js

在前面的这个例子中我们运用了JSZip外还使用了FileSaver.js这个库。FileSaver.js是在客户端保存文件的解决方案,非常适合在客户端生成文件。

在上一节的例子中,我们就是通过FileSaver.js把我们生成的.zip文件保存了下来。

语法

FileSaver saveAs(Blob/File/Url, optional domString filename, optional Object { autoBom })

例子

import FileSaver from 'file-saver';

const blob = new Blob(["Hello, world!"], {type: "text/plain;charset=utf-8"});
FileSaver.saveAs(blob, "hello world.txt");

更多用法点击官方文档


批量获取文件并打包下载

这两个库我们已经有所了解接下来就是实现我们的需求。这里分两步进行,第一步是获取文件;第二步是打包压缩。

需要操作的源文件地址

这里的文件地址只是一个简单的示例,实际开发的时候视情况而定。

const data = [
    {
        fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx',
        fileName: '文件一'
    },
    {
        fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx',
        fileName: '文件二'
    },
    {
        fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx',
        fileName: '文件三'
    },
    {
        fileUrl: 'https://www.xxx.com/data/data_service/20210429/144b4b1e4e457485c10fed54b8bc8d48.docx',
        fileName: '文件四'
    },
];  

获取文件

import JSZip from 'jszip';
import FileSaver from 'file-saver';
import requestFile from './requestFile'; //这里是封装的请求函数,大家用自己封装的或者Axios都行

const getFile = (url: string) => {
  return new Promise((resolve, reject) => {
    requestFile(url, {
      method: 'GET',
      responseType: 'blob'
    }).then((res:any) => {
      resolve(res)
    }).catch((error: any) => {
      reject(error)
    })
  })
}

打包压缩下载

这里主要是通过遍历地址数组,然后通过地址从后端获取文件,再进行一个批量压缩打包文件的操作,最后把压缩好的文件保存下来。

/**
 * 打包压缩下载
 * @param data  源文件数组
 * @param fileName  压缩文件的名称
 */
const compressAndDownload = (data: any[], fileName ?: string) => {
  const zip = new JSZip();
  const promises: any[] = [];  //用于存储多个promise
  data.forEach((item: any) => {
    const promise = getFile(item.fileUrl).then((res: any) => {
      const fileName = item.fileName
      zip.file(fileName, res ,{binary: true});
    })
    promises.push(promise)
  })

  Promise.all(promises).then(() => {
    zip.generateAsync({
      type: "blob",
      compression: "DEFLATE",  // STORE:默认不压缩 DEFLATE:需要压缩
      compressionOptions: {
        level: 9               // 压缩等级1~9    1压缩速度最快,9最优压缩方式
      }
    }).then((res: any) => {
      FileSaver.saveAs(res, fileName ? fileName : "压缩包.zip") // 利用file-saver保存文件
    })
  })
}

export default compressAndDownload;

参考

stuk.github.io/jszip/

github.com/eligrey/Fil…


最后

通过利用JSZip和FileSaver.js,我们可以对后端的批量文件进行一个整合打包压缩,这样既在一定程度上减少了对服务器的压力,在另一方面给人们的感觉就是下载了一个文件,不会一次性弹出很多的下载任务,也在一定程度上提高了体验。

作者:xmanlin
链接:https://juejin.cn/post/6970866355977486349
来源:掘金

链接: https://www.fly63.com/article/detial/10408

h5移动端实现图片文件上传

PC端上传文件多半用插件,引入flash都没关系,但是移动端要是还用各种冗余的插件估计得被喷死,项目里面需要做图片上传的功能,既然H5已经有相关的接口且兼容性良好,当然优先考虑用H5来实现。

前端使用js读取文件操作

首先我们定义一个input标签type=file、然后我们定义一个jsReadFiles的方法将文件作为参数;当上传文件的时候读取这个文件。图片上传成功,只是图片路径变成了base64编码的形式。

HTML5实现文件读取、编辑、保存

HTML5读取文件主要利用的就是FileReader这个API,它的使用需要从一个构造函数开始,保存文件的关键是生成文件对象,可以使用URL.createObjectURL()方法实现,该方法能返回给定对象的URL,用在<a>标签的href属性上就可以创建可下载的文件链接。

血淋淋的事实告诉你:你为什么不应该在JS文件中保存敏感信息

在JavaScript文件中存储敏感数据,不仅是一种错误的实践方式,而且还是一种非常危险的行为,长期以来大家都知道这一点。

在js文件中引入另一个js文件的实现方法总汇

比如我写了一个JS文件,这个文件需要调用另外一个JS文件,该如何实现呢?这篇文章主要介绍:在js文件中引入另一个js文件的实现

使用HTML5来实现本地文件读取和写入

最近有这样一个需求,就是在HTML页面中有个按钮导出,点击它,将构造一个文档并存储到本地文件系统中。另外还有个按钮,点击它,从本地文件系统中读取一个文件并对内容进行分析。

lock文件_我们为什么需要 lock 文件

从 Yarn 横空出世推出 lock 文件以来,已经两年多时间了,npm 也在 5.0 版本加入了类似的功能,lock 文件越来越被开发者们接收和认可。本篇文章想从前端视角探讨一下我们为什么需要 lock 文件,以及它的一些成本与风险,当然其中一些观点对于后端也是适用的

什么是断点续传?前端如何实现文件的断点续传

什么是断点续传?就是下载文件时,不必重头开始下载,而是从指定的位置继续下载,这样的功能就叫做断点续传。前端通过FileList对象获取到相应的文件,按照指定的分割方式将大文件分段,然后一段一段地传给后端,后端再按顺序一段段将文件进行拼接。

form表单文件上传_multipart/form-data文件上传

form表单的enctype属性:规定了form表单数据在发送到服务器时候的编码方式.。application/x-www-form-urlencoded:默认编码方式,multipart/form-data:指定传输数据为二进制数据,例如图片、mp3、文件,text/plain:纯文本的传输。空格转换为“+”,但不支持特殊字符编码。

使用HttpClient发送文件流到服务器端

适用场景: 网络绝对路径的URL文件或图片,不存储到本地,转换成stream,直接使用HTTPClient传送到SpringBoot的服务端,将文件存储下来,并返回一个文件地址。目前分层架构的系统越来越多这种需求,所以记录下来以备不时之需。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!