I have a React client and a Node server. When I send a POST request to the server, server should zip the folder and download it to the client. This cannot be done. A broken archive is downloaded to the client.
Moreover, the archive on the server is created correctly.
Below code example
React client
function test() {
fetch("http://localhost:5000/download", {
method: 'POST'
})
.then(res => res.blob())
.then(data => {
let url = URL.createObjectURL(data)
let anchor = document.createElement('a')
anchor.href = url
anchor.download = 'ex_new.zip'
document.body.appendChild(anchor)
anchor.style = 'display: none'
anchor.click()
anchor.remove()
URL.revokeObjectURL(url)
document.removeChild(anchor)
})
}
function App() {
return (
<button onClick={() => test()}>Test</button>
);
}
export default App;
Node server
const archiver = require("archiver")
const express = require("express")
const cors = require("cors")
const fs = require("fs")
const path = require('path')
const app = express()
app.use(cors())
app.post("/download", (req, res) => {
const archive = archiver('zip')
archive.directory('output')
archive.finalize()
const output = fs.createWriteStream(__dirname + '/ex.zip')
archive.pipe(output)
return res.download('/home/user/Js', 'ex.zip')
})
app.listen(5000, () => console.log("Server start"))
2
Answers
The problem might be that your node server is not sending the zip file correctly. You are using
archiver
to make a zip file and write it to a stream, but you are not checking if the stream is done before you send the response. This could make the zip file broken or incomplete. You can fix this by either waiting for the stream to finish with thearchive.finalize
method, or sending the file right away with theres.attachment
method.For example:
The problem is that you don’t wait for the file to be created before writing it to the response, which causes the content length specified in the response not to match the actual length of the zip file (and the file content would be incomplete or empty).
Try like this: