JavaScript实战篇 -ajax方式实现js打包下载文件

JavaScript实战篇 -ajax方式实现js打包下载文件

一.问题描述

JavaScript实战篇 -ajax方式实现js打包下载文件

在我们日常开发中,会遇到批量下载方面的问题;如上图所示,我们要批量下载图片,接下来我们就模拟实现这个功能,并将下载文件打包下载;

二.准备工作

2.1 JSZip

JSZip 是一个 javascript 库,用于创建、读取和编辑 .zip 文件,具有可爱而简单的 API。我们使用它来打包我们的下载文件;

JavaScript实战篇 -ajax方式实现js打包下载文件

下载完成以后,我们在dist里面可以找到相关js文件;
JavaScript实战篇 -ajax方式实现js打包下载文件

使用示例:

// 初始化一个zip打包对象
var zip = new JSZip();
// 创建一个被用来打包的名为Hello.txt的文件
zip.file("Hello.txt", "Hello World\n");
// 创建一个名为images的新的文件目录
var img = zip.folder("images");
// 这个images文件目录中创建一个base64数据为imgData的图像,图像名是smile.gif
img.file("smile.gif", imgData, {base64: true});
// 把打包内容异步转成blob二进制格式
zip.generateAsync({type:"blob"}).then(function(content) {
    // content就是blob数据,这里以example.zip名称下载    
    // 使用了FileSaver.js  
    saveAs(content, "example.zip");
});

/*
最终下载的zip文件包含内容如下:
Hello.txt
images/
    smile.gif
*/

在上面的示例代码中,用到了FileSaver.js ,接下来我们介绍一下.

2.2 FileSaver.js

File Saver.js是在客户端保存文件的解决方案,对于在客户端生成文件的Web应用程序来说是完美的,但是如果该文件来自服务器,我们建议您首先尝试使用Content-Disposition附件响应头,因为它具有更多的跨浏览器兼容性。

使用示例:

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

更多用法,请阅读File Saver.js

2.3 XMLHttpRequest

请阅读XMLHttpRequest - Web API 接口参考 | MDN

2.4 FileReader

请阅读FileReader - Web API 接口参考 | MDN

三.解决方案

<script>
    //定义文件名称
    var fileNames = ["小老头.jpg", "表情.png","pdf文件.pdf","excel文件.xlsx","故意错误文件.png"];
	//文件下载路径
    var urlsArr =["https://hx-pro.oss-cn-hangzhou.aliyuncs.com/68bb0ac4-af6e-41fa-9a91-462f128c82b5.jpg",
    "https://hx-pro.oss-cn-hangzhou.aliyuncs.com/48ccd15f-c12f-4346-b761-048b6f564fce.png",
    "https://hx-pro.oss-cn-hangzhou.aliyuncs.com/b1c6bf5e-b9e5-4381-bdb4-de440f674b12.pdf",
    "https://hx-pro.oss-cn-hangzhou.aliyuncs.com/1f60a6de-28d4-4e65-b213-c27a50dcd813.xlsx",
    "https://hx-pro.oss-cn-hangzhou.aliyuncs.com/404.png"] ;//大文件
    //渲染好的base64数据
    var base64Arr = new Array(urlsArr.length);
	//当前下载数量
    var alreadyDrawingNum = 0;
    var zip = new JSZip();
    //zip.file("readme.txt", "可在里面写相关信息");
    //zip包里面的文件夹
    var myFileZip = zip.folder("张三相关资料"); 
    var saveFileName = "2019-12-30张三资料";
  	//开始渲染
    getBase64ByAjax(urlsArr); 

//请求获取对应文件的base64码
function getBase64ByAjax(urlsArr) {
    for (let i = 0; i < urlsArr.length; i++) {
        let xhr = new XMLHttpRequest();
        //初始化一个请求
        xhr.open('get', urlsArr[i], true);
        xhr.diyData = {
            "thisIndex": i
        };
        //一个用于定义响应类型的枚举值
        xhr.responseType = 'blob';
        //xhr.setRequestHeader("www11", "8899");
        xhr.onload = function() {
            let thisFileindex = this.diyData.thisIndex;
            let thisFileStatus = this.status;
            console.log(this.diyData.thisIndex);
            if (thisFileStatus == 200) {
                var blob = this.response;
                var reader = new FileReader();
                reader.readAsDataURL(blob); // 转换为base64,可以直接放入a标签href
				reader.onload = function(e) {
                    //console.log(e.target.result);
                    console.log(thisFileindex + "-200-" + thisFileStatus);
                    base64Arr[thisFileindex] = ((e.target.result).split(',')[1]); //去头部
								//通知渲染完成
								alreadyDrawingNum = alreadyDrawingNum + 1;
							}
						} else {
							console.log(thisFileindex + "-504-" + thisFileStatus);
							fileNames[thisFileindex] = fileNames[thisFileindex] + "(!!此文件下载错误" + thisFileStatus + ").txt";
							base64Arr[thisFileindex] = (""); //错误
							//通知渲染完成
							alreadyDrawingNum = alreadyDrawingNum + 1;
						}
					};
					xhr.send();
				}
			}

//每个n时间看是否渲染完成,完成后保存
function isCompletedToBase64() {

    setTimeout(function() {
        console.log("****正在请求", alreadyDrawingNum);
        if (urlsArr.length == alreadyDrawingNum) {
            console.log("已完成渲染开始保存:", base64Arr);
            saveFile();
            $("#xiazai").text("下载完成");

        } else {

            $("#xiazai").append(".");
            console.log("下载了" + base64Arr.length); //可在html里面设置进度条
            isCompletedToBase64();
        }
    }, 100);

}
isCompletedToBase64();
$("#xiazai").text("正在下载");


function saveFile() {

    for (let i = 0; i < base64Arr.length; i++) {

        let fileName = fileNames[i]; //里面单独文件名

        myFileZip.file(fileName, base64Arr[i], {
            base64: true
        });
    }
    zip.generateAsync({
        type: "blob"
    }).then(function(content) {
        // see FileSaver.js
        saveAs(content, "下载文件" + ".zip");
    });
}
</script>

效果图:
JavaScript实战篇 -ajax方式实现js打包下载文件

四.小结

采用XMLHttpRequest ajax请求方式好处是:

1.能下载任意类型文件。

2.如果浏览器之前缓存过,可以从缓存里面直接加载图片。名字可以根据数组一一对应,网上方法一般不能对应名字。

3.自定义下载错误类型文本提示

五.附录

源码下载:ajax请求方式打包下载所有类型文件源码

参考文章

1.JS实现zip打包文件并下载

2.浏览器中利用js打包下载所有类型文件

上一篇:ckeditor上粘贴从word中copy的图片和文字


下一篇:Java mysql blob 数据读写操作