如何从后端发送文件至浏览器下载?Blob体积异常问题求助
问题原因
浏览器前端请求时,请求库(比如axios)默认会把响应解析成UTF-8字符串,二进制文件(图片、文档等)被转成字符串后再生成Blob,会出现编码错误,导致文件体积变大、内容损坏,无法正常打开。而Postman/Thunder Client会自动识别并处理二进制响应,所以能正常保存文件。
解决方案
1. 前端修复(核心)
必须告诉请求库不要解析响应,直接返回二进制数据。以axios为例,修改请求配置并调整前端下载逻辑:
// 先修改downloadFile的请求配置 const downloadFile = (id: string) => { return axios.get(`/files/download/${id}`, { responseType: 'blob' // 关键:指定响应类型为Blob,避免字符串解析 }); }; async downloadFiles(id: string) { try { const { data, headers } = await downloadFile(id); const url = window.URL.createObjectURL(data); const link = document.createElement('a'); link.href = url; // 从响应头获取文件名,避免前端硬编码 const contentDisposition = headers['content-disposition']; let filename = '未知文件'; if (contentDisposition) { const match = contentDisposition.match(/filename="?([^"]+)"?/); filename = match?.[1] || filename; } link.setAttribute('download', filename); document.body.appendChild(link); link.click(); link.remove(); window.URL.revokeObjectURL(url); // 释放内存,避免泄漏 } catch (error) { console.error('下载失败:', error); } }
2. 后端优化(可选但推荐)
- 不要把整个文件读进内存(
fs.readFileSync),直接用文件流传输,降低大文件场景下的内存占用 - 对文件名编码,避免中文/特殊字符导致的乱码问题
router.get('/files/download/:id', async (req, res) => { try { const { id } = req.params; const file = await FileArea.findById(id); if (!file) { return res.status(404).send('File not found'); } if (fs.existsSync(file.path)) { // 直接创建文件读取流,无需预加载文件内容 const readStream = fs.createReadStream(file.path); // 编码文件名,兼容中文 res.set('Content-Disposition', `attachment; filename="${encodeURIComponent(file.name)}"`); res.set('Content-Type', file.type); readStream.pipe(res); // 监听流错误,避免崩溃 readStream.on('error', () => res.status(500).send('Internal server error')); } else { return res.status(404).send('File not found'); } } catch (error) { return res.status(500).send('Internal server error'); } });
内容的提问来源于stack exchange,提问作者rmb
相关产品推荐
相关产品推荐

