I am engaged on a file obtain characteristic in my Node.js + Categorical backend and React frontend. The obtain works superb on most browsers, however I’m experiencing the next points solely on iOS Firefox:
The filename seems as “Unknown” as a substitute of the anticipated filename.
The file dimension initially shows appropriately earlier than the obtain begins, however the downloaded file is way smaller than anticipated (e.g., it needs to be a number of MB however downloads as 187KB).
The downloaded file seems to be empty.
Backend Code (Node.js + Categorical)
I am utilizing fs.createReadStream to stream the file to the response:
const fs = require('fs');
const path = require('path');
exports.downloadFile = (req, res, subsequent) => {
attempt {
console.log('Obtain endpoint hit');
const filepath = req.physique.filepath;
const filename = path.basename(filepath);
const encodedFilename = encodeURIComponent(filename).exchange(/%20/g, ' ');
let stat;
attempt {
stat = fs.statSync(filepath);
} catch (err) {
console.error('File not discovered:', filepath);
return res.standing(404).json({ success: false, msg: 'File not discovered' });
}
res.standing(200);
res.setHeader('Content material-Disposition', `attachment; filename*=UTF-8''${encodedFilename}`);
res.setHeader('Content material-Sort', 'software/octet-stream';);
res.setHeader('Settle for-Ranges', 'bytes');
res.setHeader('Content material-Size', stat.dimension);
res.flushHeaders();
const fileStream = fs.createReadStream(filepath);
fileStream.pipe(res);
fileStream.on('error', (err) => {
console.error('File stream error:', err);
if (!res.headersSent) {
res.standing(500).json({ success: false, msg: 'File obtain failed' });
}
});
fileStream.on('finish', () => {
console.log('File despatched efficiently.');
res.finish();
});
} catch (error) {
subsequent(error);
}
};
Frontend Code (React)
On the frontend, I am dealing with the obtain like this:
.then((response) => {
const blob = new Blob([response.data], { kind: response.headers['content-type'] });
const url = URL.createObjectURL(blob);
const hyperlink = doc.createElement('a');
hyperlink.href = url;
hyperlink.obtain = filenames[index];
hyperlink.click on();
setTimeout(() => {
hyperlink.take away();
URL.revokeObjectURL(url); // Launch reminiscence
}, 500);
})
.catch((error) => {
console.error(`Error downloading file ${filenames[index]}:`, error);
});
- Checked that Content material-Disposition is correctly set (filename*=UTF-8”${encodedFilename}).
- Ensured that Content material-Size is appropriately set to the precise file dimension.
- Verified that fs.createReadStream(filepath) appropriately reads the file.
- Tried utilizing a plain res.obtain(filepath) as a substitute of fs.createReadStream, however the subject persists.
- Examined on Chrome/Safari on iOS and every thing works superb—solely Firefox on iOS has this subject.
Questions:
- Why does solely iOS Firefox present “Unknown” because the filename?
- Why is the downloaded file empty or a lot smaller than anticipated?
- Is there an alternate method to deal with file downloads that works persistently throughout browsers, particularly on iOS Firefox?
- Any assist could be drastically appreciated! Thanks upfront.