Javascript 如何在循环所有文件后创建zip文件?
我正在使用JSzip创建包含所有图像文件的zipfile。我使用XMLHttpRequest从循环中的外部链接获取图像。根据我的代码,在完成XMLHttpRequest之前创建zipfile。所以它返回空的zip文件。如何在循环所有文件后创建zip文件Javascript 如何在循环所有文件后创建zip文件?,javascript,for-loop,xmlhttprequest,Javascript,For Loop,Xmlhttprequest,我正在使用JSzip创建包含所有图像文件的zipfile。我使用XMLHttpRequest从循环中的外部链接获取图像。根据我的代码,在完成XMLHttpRequest之前创建zipfile。所以它返回空的zip文件。如何在循环所有文件后创建zip文件 $(document).on('click', '.download', function(){ var path = $(this).attr("data-id"); var count = $(this).attr("val
$(document).on('click', '.download', function(){
var path = $(this).attr("data-id");
var count = $(this).attr("value");
var storageRef = firebase.storage().ref();
var zip = new JSZip();
console.log(count);
for (i = 1; i <= count; i++) {
console.log(path+i+".png");
var imagePath = path+i+".png";
// Create a reference to the file we want to download
var starsRef = storageRef.child(imagePath);
starsRef.getDownloadURL().then(function(url) {
// Insert url into an <img> tag to "download"
ImageUrl = url;
var xhr = new XMLHttpRequest();
xhr.open('GET', ImageUrl, true);
xhr.responseType = "arraybuffer";
xhr.onreadystatechange = function(evt) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
zip.file(i+".png", xhr.response);
}
}
};
xhr.send();
})
}
zip.generateAsync({type:"blob"})
.then(function(content) {
// see FileSaver.js
saveAs(content, "my.zip");
});
});
$(文档).on('click','download',function(){
var path=$(this.attr(“数据id”);
var count=$(this.attr(“value”);
var storageRef=firebase.storage().ref();
var zip=newjszip();
控制台日志(计数);
对于(i=1;iJSZip支持承诺作为内容:您可以将每个HTTP调用包装成承诺,而不是显式地等待
第一个函数downloadUrlAsPromise
将xhr调用包装成一个承诺。第二个函数downloadFirebaseImage
将getDownloadURL
的承诺与第一个函数的承诺链接起来。结果是xhr内容的承诺
一旦你做到了这一点,你就可以直接向JSZip承诺如下:
zip.file(i+".png", downloadFirebaseImage(imagePath));
完整方法:
function downloadUrlAsPromise (url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = "arraybuffer";
xhr.onreadystatechange = function(evt) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(xhr.response);
} else {
reject(new Error("Ajax error for " + url + ": " + xhr.status));
}
}
});
xhr.send();
});
}
function downloadFirebaseImage(storageRef, path) {
var starsRef = storageRef.child(imagePath);
return starsRef.getDownloadURL().then(function(url) {
return downloadUrlAsPromise(url);
});
}
// ...
for (i = 1; i <= count; i++) {
console.log(path+i+".png");
var imagePath = path+i+".png";
zip.file(i+".png", downloadFirebaseImage(imagePath));
}
zip.generateAsync({type:"blob"})
.then(function(content) {
// see FileSaver.js
saveAs(content, "my.zip");
});
函数下载urlaspromise(url){
返回新承诺(功能(解决、拒绝){
var xhr=new XMLHttpRequest();
xhr.open('GET',url,true);
xhr.responseType=“arraybuffer”;
xhr.onreadystatechange=函数(evt){
if(xhr.readyState==4){
如果(xhr.status==200){
解析(xhr.response);
}否则{
拒绝(新错误(“+url+”:“+xhr.status”)的Ajax错误);
}
}
});
xhr.send();
});
}
函数下载FireBaseImage(storageRef,路径){
var starsRef=storageRef.child(imagePath);
返回starsRef.getDownloadURL().then(函数(url){
返回下载url地址(url);
});
}
// ...
对于(i=1;我似乎您在循环完成之前调用了zip.generateAsync
,因此它可以在您第一次调用zip.file(i+“.png”,xhr.response)”之前执行;
。我假设如果您将循环包装成promise
,您可以根据需要链接zip.generateAsync
。这可能会有所帮助► 是的。正如我在问题中所说的,这就是问题所在。问题是我不知道如何克服这种情况。我认为这比ajax请求更难实现。除了@Fran的注释外,使用一些关键字如搜索SO会给出很多结果。@Bandara我链接了一篇SO帖子,展示了如何使用承诺。这会告诉你如何克服这个问题。效果很好。谢谢。