gua*_*ari 5 javascript zip download save-as google-chrome-extension
我正在创建一个Chrome扩展程序,需要从网站下载多个文件(图像和/或视频).这些文件可能有很大的大小,所以我想向用户显示下载进度.经过一些研究,我发现目前可能的解决方案可能是:
我被困在第2段),如何压缩下载的文件?
要理解,这是一个代码示例:
var fileURLs = ['http://www.test.com/img.jpg',...];
var zip = new JSZip();
var count = 0;
for (var i = 0; i < fileURLs.length; i++){
var xhr = new XMLHttpRequest();
xhr.onprogress = calculateAndUpdateProgress;
xhr.open('GET', fileURLs[i], true);
xhr.responseType = "blob";
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
var blob_url = URL.createObjectURL(response);
// add downloaded file to zip:
var fileName = fileURLs[count].substring(fileURLs[count].lastIndexOf('/')+1);
zip.file(fileName, blob_url); // <- here's one problem
count++;
if (count == fileURLs.length){
// all download are completed, create the zip
var content = zip.generate();
// then trigger the download link:
var zipName = 'download.zip';
var a = document.createElement('a');
a.href = "data:application/zip;base64," + content;
a.download = zipName;
a.click();
}
}
};
xhr.send();
}
function calculateAndUpdateProgress(evt) {
if (evt.lengthComputable) {
// get download progress by performing some average
// calculations with evt.loaded, evt.total and the number
// of file to download / already downloaded
...
// then update the GUI elements (eg. page-action icon and popup if showed)
...
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码生成一个包含小损坏文件的可下载存档.文件名同步也存在问题:blob对象不包含文件名,因此如果.fileURLs[0]需要更多时间下载而不是fileURLs[1]名称变错(倒置)..
注意:我知道Chrome有一个下载API,但它在开发频道中,所以不幸的是它现在不是解决方案,我想避免使用NPAPI来完成这么简单的任务.
我的解决方案使用Axios,FileSaver.js和JSZip
import JSZip from "jszip";
import axios from "axios";
import { saveAs } from "file-saver";
const zip = new JSZip();
const fileArr = [
{
name: "file1.jpg",
url: "https://url.com/file1.jpg",
},
{
name: "file2.docx",
url: "https://url.com/file2.docx",
},
{
name: "file3.pdf",
url: "https://url.com/file3.pdf",
},
];
const download = (item) => {
//download single file as blob and add it to zip archive
return axios.get(item.url, { responseType: "blob" }).then((resp) => {
zip.file(item.name, resp.data);
});
};
//call this function to download all files as ZIP archive
const downloadAll = () => {
const arrOfFiles = fileArr.map((item) => download(item)); //create array of promises
Promise.all(arrOfFiles)
.then(() => {
//when all promises resolved - save zip file
zip.generateAsync({ type: "blob" }).then(function (blob) {
saveAs(blob, "hello.zip");
});
})
.catch((err) => {
console.log(err);
});
};
Run Code Online (Sandbox Code Playgroud)
我被提醒了这个问题..因为它还没有答案,我写了一个可能的解决方案,以防它对其他人有用:
因此,修改后的上层代码可以是:
var fileURLs = ['http://www.test.com/img.jpg',...];
var zip = new JSZip();
var count = 0;
downloadFile(fileURLs[count], onDownloadComplete);
function downloadFile(url, onSuccess) {
var xhr = new XMLHttpRequest();
xhr.onprogress = calculateAndUpdateProgress;
xhr.open('GET', url, true);
xhr.responseType = "blob";
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (onSuccess) onSuccess(xhr.response);
}
function onDownloadComplete(blobData){
if (count < fileURLs.length) {
blobToBase64(blobData, function(binaryData){
// add downloaded file to zip:
var fileName = fileURLs[count].substring(fileURLs[count].lastIndexOf('/')+1);
zip.file(fileName, binaryData, {base64: true});
if (count < fileURLs.length -1){
count++;
downloadFile(fileURLs[count], onDownloadCompleted);
}
else {
// all files have been downloaded, create the zip
var content = zip.generate();
// then trigger the download link:
var zipName = 'download.zip';
var a = document.createElement('a');
a.href = "data:application/zip;base64," + content;
a.download = zipName;
a.click();
}
});
}
}
function blobToBase64(blob, callback) {
var reader = new FileReader();
reader.onload = function() {
var dataUrl = reader.result;
var base64 = dataUrl.split(',')[1];
callback(base64);
};
reader.readAsDataURL(blob);
}
function calculateAndUpdateProgress(evt) {
if (evt.lengthComputable) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
最后请注意,如果您下载少量文件(小于10个文件的整体大小不到1MB),这个解决方案效果很好,在其他情况下,JSZip会在生成存档时崩溃浏览器选项卡,所以它使用分离的线程进行压缩(WebWorker,如zip.js)是一个更好的选择.
如果之后生成了归档文件,浏览器仍会继续崩溃大文件而不报告任何错误,尝试触发saveAs窗口而不传递二进制数据,但是通过传递blob引用(a.href = URL.createObjectURL(zippedBlobData);其中zippedBlobData是blob对象引用的生成的档案数据);
| 归档时间: |
|
| 查看次数: |
16824 次 |
| 最近记录: |