将图像链接转换为 base64 并使用 JSZip 将它们添加到 zip 文件
Conversion image links to base64 and adding them to zip file using JSZip
所以基本上我想在 zip 文件中添加一些图像并能够下载它。我有两个变量保存图像源 - pic1, pic2 和一个全局变量 basePic 用于保存 base64 字符串。我有一个将图像转换为 base64 的函数:
var pic; //http://www.somesite.com/i/picture.jpg
var pic2; //http://www.somesite.com/i/picture2.jpg
var basePic;// base64 string of an image
function getBase64FromImageUrl(url) {
var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.onload = function () {
var canvas = document.createElement("canvas");
canvas.width =this.width;
canvas.height =this.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);
var dataURL = canvas.toDataURL("image/png");
basePic=dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
};
img.src = url; // I was trying to put this after setAttribute, but it's the same effect
}
稍后我将尝试创建一个 zip 文件并像这样调用此函数:
var zip = new JSZip();
getBase64FromImageUrl(pic);
alert("random text"); // without it, it's just empty file added to zip
zip.file("picture.png",basePic, {base64: true});
getBase64FromImageUrl(pic2);
alert("random text");
zip.file("picture2.png",basePic, {base64: true});
zip.generateAsync({type:"blob"})
.then(function(content) {
saveAs(content, "example.zip");
});
此函数适用于一张图片,但多张图片会更加随机。如果我 运行 我的代码几次而不刷新页面,它可能会得到我需要的结果。但是我的 zip 文件中的大部分时间只是第二张图片两次,我必须在调用此函数后 alert 一些东西,因为 basePic 会是空无。我想修复此功能,以便能够轻松地将多个图像源转换为 base64 字符串。
1.How 使此功能正常工作,input_url -> output_base64,多张图片 ?
2.How 无需在每次调用该函数后发出警报即可做到这一点 ?
问题是压缩过程在图像加载之前就开始了。将文件添加到 zip 存档的过程必须从 onload
处理程序内部开始。
但是,这里也有几点需要考虑:
- 如果您想按原样将图像添加到存档中,则无需通过 canvas
- 与 Data-URI 之间的转换非常昂贵并且占用大量内存。 JSZip 在内部使用 pako_delate,这在类型化数组视图中效果更好 (
Uint8Array
)
我建议改用以下方法:
- 在应用开始时(或开始加载文件之前)创建 zip 对象
- 使用
XMLHttpRequest
加载每个文件并请求内容为 ArrayBuffer
。这将允许您将任何类型的文件直接加载为二进制格式,从而提高性能和资源。
- 随时添加文件
- 传递完所有 URL 后调用
generateAsync()
方法,您应该完成。
例子
这不是可用于生产的示例,也不打算成为,但它将显示主要步骤。根据您的情况进行调整,在适当的地方添加错误处理和健全性检查。
// create archive before loading process begin
var zip = new JSZip();
// image list to add:
var images = [
"//i.imgur.com/qDFCWVnb.jpg",
"//i.imgur.com/VBvzEq1b.jpg",
"//i.imgur.com/ZWtUEuLb.jpg"
],
index = 0; // for loader
// function to load a single image as arraybuffer using XMLHttpRequests
// it will assume cross-origin usage is allowed
function loadAsArrayBuffer(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.responseType = "arraybuffer";
xhr.onerror = function() {/* handle errors*/};
xhr.onload = function() {
if (xhr.status === 200) {callback(xhr.response, url)}
else {/* handle errors*/}
};
xhr.send();
}
// loading process. Here it will load one and one image.
// You can modify it to load several at once but some browsers put
// a cap on how many XHR connections can be open at the same time..
(function load() {
if (index < images.length) {
loadAsArrayBuffer(images[index++], function(buffer, url) {
var filename = getFilename(url);
zip.file(filename, buffer); // image has loaded, add it to archive
load(); // load next image
})
}
else { // done! present archive somehow
zip.generateAsync({type:"blob"}).then(function(content) {
// save out
lnk.href = (URL || webkitURL).createObjectURL(content);
lnk.innerHTML = "Right-click + Save as to download zip file";
lnk.download = "DemoZip.zip";
});
}
})();
// Just for this demo! keep separate array with filename or
// modify to allow for "filename-less" uris.
function getFilename(url) {
return url.substr(url.lastIndexOf("/") + 1)
}
<script src="https://raw.githubusercontent.com/Stuk/jszip/master/dist/jszip.min.js"></script>
Loading external lib + images... hold on...
<br><a id=lnk></a>
所以基本上我想在 zip 文件中添加一些图像并能够下载它。我有两个变量保存图像源 - pic1, pic2 和一个全局变量 basePic 用于保存 base64 字符串。我有一个将图像转换为 base64 的函数:
var pic; //http://www.somesite.com/i/picture.jpg
var pic2; //http://www.somesite.com/i/picture2.jpg
var basePic;// base64 string of an image
function getBase64FromImageUrl(url) {
var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.onload = function () {
var canvas = document.createElement("canvas");
canvas.width =this.width;
canvas.height =this.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(this, 0, 0);
var dataURL = canvas.toDataURL("image/png");
basePic=dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
};
img.src = url; // I was trying to put this after setAttribute, but it's the same effect
}
稍后我将尝试创建一个 zip 文件并像这样调用此函数:
var zip = new JSZip();
getBase64FromImageUrl(pic);
alert("random text"); // without it, it's just empty file added to zip
zip.file("picture.png",basePic, {base64: true});
getBase64FromImageUrl(pic2);
alert("random text");
zip.file("picture2.png",basePic, {base64: true});
zip.generateAsync({type:"blob"})
.then(function(content) {
saveAs(content, "example.zip");
});
此函数适用于一张图片,但多张图片会更加随机。如果我 运行 我的代码几次而不刷新页面,它可能会得到我需要的结果。但是我的 zip 文件中的大部分时间只是第二张图片两次,我必须在调用此函数后 alert 一些东西,因为 basePic 会是空无。我想修复此功能,以便能够轻松地将多个图像源转换为 base64 字符串。
1.How 使此功能正常工作,input_url -> output_base64,多张图片 ?
2.How 无需在每次调用该函数后发出警报即可做到这一点 ?
问题是压缩过程在图像加载之前就开始了。将文件添加到 zip 存档的过程必须从 onload
处理程序内部开始。
但是,这里也有几点需要考虑:
- 如果您想按原样将图像添加到存档中,则无需通过 canvas
- 与 Data-URI 之间的转换非常昂贵并且占用大量内存。 JSZip 在内部使用 pako_delate,这在类型化数组视图中效果更好 (
Uint8Array
)
我建议改用以下方法:
- 在应用开始时(或开始加载文件之前)创建 zip 对象
- 使用
XMLHttpRequest
加载每个文件并请求内容为ArrayBuffer
。这将允许您将任何类型的文件直接加载为二进制格式,从而提高性能和资源。 - 随时添加文件
- 传递完所有 URL 后调用
generateAsync()
方法,您应该完成。
例子
这不是可用于生产的示例,也不打算成为,但它将显示主要步骤。根据您的情况进行调整,在适当的地方添加错误处理和健全性检查。
// create archive before loading process begin
var zip = new JSZip();
// image list to add:
var images = [
"//i.imgur.com/qDFCWVnb.jpg",
"//i.imgur.com/VBvzEq1b.jpg",
"//i.imgur.com/ZWtUEuLb.jpg"
],
index = 0; // for loader
// function to load a single image as arraybuffer using XMLHttpRequests
// it will assume cross-origin usage is allowed
function loadAsArrayBuffer(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.responseType = "arraybuffer";
xhr.onerror = function() {/* handle errors*/};
xhr.onload = function() {
if (xhr.status === 200) {callback(xhr.response, url)}
else {/* handle errors*/}
};
xhr.send();
}
// loading process. Here it will load one and one image.
// You can modify it to load several at once but some browsers put
// a cap on how many XHR connections can be open at the same time..
(function load() {
if (index < images.length) {
loadAsArrayBuffer(images[index++], function(buffer, url) {
var filename = getFilename(url);
zip.file(filename, buffer); // image has loaded, add it to archive
load(); // load next image
})
}
else { // done! present archive somehow
zip.generateAsync({type:"blob"}).then(function(content) {
// save out
lnk.href = (URL || webkitURL).createObjectURL(content);
lnk.innerHTML = "Right-click + Save as to download zip file";
lnk.download = "DemoZip.zip";
});
}
})();
// Just for this demo! keep separate array with filename or
// modify to allow for "filename-less" uris.
function getFilename(url) {
return url.substr(url.lastIndexOf("/") + 1)
}
<script src="https://raw.githubusercontent.com/Stuk/jszip/master/dist/jszip.min.js"></script>
Loading external lib + images... hold on...
<br><a id=lnk></a>