I'm working on a file download feature in my Node.js + Express backend and React frontend. The download works fine on most browsers, but I’m experiencing the following issues only on iOS Firefox:
The filename appears as "Unknown" instead of the expected filename. The file size initially displays correctly before the download starts, but the downloaded file is much smaller than expected (e.g., it should be several MB but downloads as 187KB). The downloaded file appears to be empty.
Backend Code (Node.js + Express) I'm using fs.createReadStream to stream the file to the response:
const fs = require('fs');
const path = require('path');
exports.downloadFile = (req, res, next) => {
try {
console.log('Download endpoint hit');
const filepath = req.body.filepath;
const filename = path.basename(filepath);
const encodedFilename = encodeURIComponent(filename).replace(/%20/g, ' ');
let stat;
try {
stat = fs.statSync(filepath);
} catch (err) {
console.error('File not found:', filepath);
return res.status(404).json({ success: false, msg: 'File not found' });
}
res.status(200);
res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${encodedFilename}`);
res.setHeader('Content-Type', 'application/octet-stream';);
res.setHeader('Accept-Ranges', 'bytes');
res.setHeader('Content-Length', stat.size);
res.flushHeaders();
const fileStream = fs.createReadStream(filepath);
fileStream.pipe(res);
fileStream.on('error', (err) => {
console.error('File stream error:', err);
if (!res.headersSent) {
res.status(500).json({ success: false, msg: 'File download failed' });
}
});
fileStream.on('end', () => {
console.log('File sent successfully.');
res.end();
});
} catch (error) {
next(error);
}
};
Frontend Code (React) On the frontend, I'm handling the download like this:
.then((response) => {
const blob = new Blob([response.data], { type: response.headers['content-type'] });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = filenames[index];
link.click();
setTimeout(() => {
link.remove();
URL.revokeObjectURL(url); // Release memory
}, 500);
})
.catch((error) => {
console.error(`Error downloading file ${filenames[index]}:`, error);
});
- Checked that Content-Disposition is properly set (filename*=UTF-8''${encodedFilename}).
- Ensured that Content-Length is correctly set to the actual file size.
- Verified that fs.createReadStream(filepath) correctly reads the file.
- Tried using a plain res.download(filepath) instead of fs.createReadStream, but the issue persists.
- Tested on Chrome/Safari on iOS and everything works fine—only Firefox on iOS has this issue.
Questions:
- Why does only iOS Firefox show "Unknown" as the filename?
- Why is the downloaded file empty or much smaller than expected?
- Is there an alternative way to handle file downloads that works consistently across browsers, especially on iOS Firefox?
- Any help would be greatly appreciated! Thanks in advance.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744907225a4600329.html
评论列表(0条)