I am trying to download a zip file using a ReactJS client. The zip file is created at backend side (Node JS).
My React client does the following:
{this.state.selectedRows.length > 0 &&
<>
<Tooltip title="Baixar arquivos" arrow>
<IconButton
onClick={() => {
const dcs = (!!this.state.selectedRows && this.state.selectedRows.length === 0) ? this.state.fls.map(f => f.doc_id ) : this.state.selectedRows
this.props.api.post('/mediateca/downloadzipfile', { docs: dcs }).then(r => {
this.setState({ selectedRows: [] })
var blob = new Blob([r], { type: "application/octet-stream" });
saveAs(blob, "example.zip")
})
}}>
<FileDownload />
</IconButton>
</Tooltip>
<D size="0.5rem" />
</>
}
If I print the post response ( "console.log(r)") I see a string like "PK<0x03><0x04><0x14>...", but longer (it seems to be the ASCII sequence of a zip file). I makes the download example.zip file with 238,2 kB. However, no zip application is able to open it.
More over, at backend Node JS side, I have the post route triggering this method:
async downloadZIPfile(ctx) {
let u = await ctx.auth.getUser()
Log.create(!!u ? u.email : "null", ctx.request.url())
const { docs } = ctx.request.all()
const rdocs = !!docs && docs.length > 0 ? docs : []
//Recupera os pdfs do banco de dados e salva um zip no /tmp
if(rdocs.length > 0){
var zip = new AdmZip()
for(let x in rdocs){
const doc = await Documentos.findOne({ where: { id: rdocs[x] } })
if (!!doc) {
const file = await Arquivos.findOne({ where: { id: doc.arquivo_id } })
var filePath = "/tmp/"+rdocs[x]+".pdf"
zip.addFile(rdocs[x]+".pdf",file.binario)
}
}
var data = zip.toBuffer()
var fileName = "flavio.zip"
zip.writeZip("/tmp/"+fileName)
ctx.response.header('Content-Type', 'application/octet-stream')
ctx.response.header('Content-Disposition', `attachment; filename=${fileName}`)
ctx.response.header('Content-Length', data.length)
ctx.response.send(data);
}
else {
ctx.response.status(404).send()
}
return { status: 'ok' }
}
}
Note that this method saves a flavio.zip 130,8KB file for debugging. It can be opened correctly by any zip application.
So, what is wrong with my React client POST response?
I am trying to download a zip file using a ReactJS client. The zip file is created at backend side (Node JS).
the issue might be with how you're handling the response in your ReactJS client. Instead of directly passing the response data to the saveAs function, you should create a new Blob object from the response data and then pass that to the saveAs function.
this.props.api.post('/mediateca/downloadzipfile', { docs: dcs }, { responseType: 'arraybuffer' }).then(response => {
const blob = new Blob([response.data], { type: 'application/octet-stream' })
saveAs(blob, 'example.zip')
})
In this code, we're setting the responseType option to 'arraybuffer' so that the response data is returned as an ArrayBuffer object, which we can then use to create a new Blob object. We're passing this Blob object and the desired filename to the saveAs function to trigger the download.