While attempting to generate a zip file using JSZip, I encounter issues where the images are falsely flagged as not being instances of Blob or the final result turns out to be corrupt and cannot be extracted.
The process involves an API on the back-end that returns .png images based on specific ids obtained from an authenticated endpoint. Within the server component, the image ids are fetched from a separate endpoint and converted into an array of .png images (as Blob objects) using await res.blob()
. Subsequently, these images are combined into a zip file using JSZip, which is then returned as a Buffer object.
On the client side, the Buffer object is received, converted into a Blob object, and an URL is created for downloading purposes.
The server-side script:
const download = async (file, format: string) => {
"server-side function"
const imageArray = await makeImageArray(file.id, format);
const zip = new JSZip();
await Promise.all(imageArray.map(async (rendered) => {
console.log("blob", rendered.data)
zip.file(`${rendered.name.replaceAll(" ", "_")}.${rendered.type}`, Buffer.from(await rendered.data.arrayBuffer()).toString("base64"), {base64: true});
return rendered.data;
}));
const zipped = await zip.generateAsync({type: "blob"})
const arrayBuffer = await zipped.arrayBuffer();
const buffer = Buffer.from(arrayBuffer)
return buffer
}
The client-side script:
const clickAZip = async (file, format) => {
const a = document.createElement("a");
const zip = await onDownload(file, format)
a.href = URL.createObjectURL(new Blob(zip,{type: 'application/zip'}))
a.download=`${file.name}.zip`
a.click()
}
Note that the current code downloads a corrupted zip archive. If replacing
rendered.data.arrayBuffer()).toString("base64"
with rendered.data
, it results in the error message within the server component:
Internal error: Error: Can't read the data of 'Generic_image.png'. Is it in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?
Edit:
The potentially problematic code for the makeImageArray
function:
const makeImageArray = async (id: string, format: string) => {
"server-side function"
return await authenticatedFetch(process.env.NEXT_PUBLIC_API_URL + `/project/sheets/all/${id}`, "GET", null)
.then(async (response) => {
return await Promise.all(response
.map(async (sheet) => {
return {
data: await blobFetch(process.env.NEXT_PUBLIC_API_URL + '/private/render', "POST", JSON.stringify({
text: sheet.text,
format: format
})), name: sheet.name, type: format
}
}))
}).then(res => res.filter(r => !r.data?.error))
}
This function takes an array of ids (Strings) from the initial fetch request and transforms them into an array of .png images through another fetch operation. The issue seems to lie in the construction of the zip file itself rather than individual image corruption.