I'm currently using docx.js in my react application I have setup with AWS Amplify (node backend). I am generating multiple documents and am saving them separately using the packer to generate the document as a blob and then use FileSaver.js's saveAs function to download. See code sample below:
const aDoc = new Document();
const bDoc = new Document();
const cDoc = new Document();
// Code that adds content to each doc
// Use packer to generate document as blob and download using FileSaver
Packer.toBlob(aDoc).then((blob) => {
// saveAs from FileSaver will download the file
FileSaver(blob, "aDoc.docx");
});
Packer.toBlob(bDoc).then((blob) => {
// saveAs from FileSaver will download the file
FileSaver(blob, "bDoc.docx");
});
Packer.toBlob(cDoc).then((blob) => {
// saveAs from FileSaver will download the file
FileSaver(blob, "cDoc.docx");
});
Now I'm wondering, how can I instead put these all into a ZIP file and have the user download that instead? Haven't really found much around, just this, which seems more like a workaround as it uses timeout to avoid issues when there are many documents--I'd rather avoid that and have it download in an archive instead. I've seen some libraries, like JSZip mentioned, but don't really understand how to get what docx.js is giving me into the archive.
Take a look at using JSZip - https://www.npmjs.com/package/jszip
I have reworked some code I used within a POC to how I believe it may work with your project and the code above.
var JSZip = require('jszip')
const Demo = () => {
const demoClick = () => {
var zip = new JSZip()
const zipFilename = 'test.zip'
const blobs = []
Packer.toBlob(aDoc).then((blob) => {
blobs.push(blob)
})
// repeat if needed
var urlArr = blobs // this will be your set of blobs you are downloading on their own right now.
urlArr.forEach(function (url) {
var filename = 'test.docx'
zip.file(filename, url, { binary: true })
})
zip.generateAsync({ type: 'blob' }).then(function (content) {
// you may need to work the content into a zip blob like this depending how FileSaver takes it
const zipContents = URL.createObjectURL(content)
//or
const zipContents = new Blob([content], {
type: 'application/zip'
})
// saveAs from FileSaver will download the file
FileSaver(content, zipFilename)
})
}
return <button onClick={demoClick}>demo</button>
}
If FileSaver doesn't like the format of the ZIP you could then use a more simple non imported download/save method
const zipContents = URL.createObjectURL(content)
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(content, zipFilename)
} else if (isIOS && isChrome) {
window.open(zipContents, '_blank')
} else {
const link = document.createElement('a')
link.href = zipContents
link.target = '_blank'
link.download = zipFilename
link.click()
}