如何在MongoDB中上传并获取PDF?解决Blob文件损坏问题
问题分析与解决方案
核心问题点
- 前端POST请求手动设置Content-Type导致解析错误:手动指定
multipart/form-data会丢失boundary信息,Axios无法正确处理FormData结构。 - 后端POST路由读取文件方式冗余易出错:multer上传的文件本身提供
buffer属性,无需通过fs.readFileSync读取本地文件路径。 - 后端GET路由错误返回JSON格式:将PDF二进制数据转为JSON返回时,会破坏原始二进制结构,导致前端生成的Blob损坏。
- GET路由查询结果处理不当:
PDF.find返回数组,若单个refId仅对应一个PDF,应使用findOne避免多余的数据结构干扰。
修正后的代码
1. React前端POST请求
移除手动设置的Content-Type,Axios会自动处理FormData的正确请求头:
const handleSubmit = async (e) => { if (configuration) { axios(configuration) .then(async (res) => { const id = res.data.result._id; try { const formData = new FormData(); formData.append('filename', licenseNo); formData.append('file', file); // 移除手动设置的Content-Type,Axios自动生成正确头部 const res = await axios.post(`url/file/${id}`, formData); console.log(res.data); } catch (err) { console.error(err); } navigate('/'); }) .catch((error) => { console.log(error.message); }); } };
2. 后端POST路由
直接使用multer提供的req.file.buffer作为PDF二进制数据:
router.post('/:id', upload.single('file'), (req, res, next) => { const pdfName = req.body.filename + '_' + req.file.originalname; // 直接使用req.file.buffer,跳过文件读取步骤 const newPDF = new PDF({ refId: req.params.id, name: pdfName, data: req.file.buffer, }); newPDF.save() .then(result => { res.status(201).json({ message: 'PDF uploaded successfully!', pdf: result }); }) .catch(err => { console.error(err); res.status(500).json({ error: err }); }); });
3. 后端GET路由
使用findOne获取单个PDF文档,直接返回原始二进制数据:
router.route('/:id').get((req, res) => { PDF.findOne({ refId: req.params.id }) .then((pdf) => { if (!pdf) { return res.status(404).json({ error: 'PDF not found' }); } // 设置正确响应头,直接发送二进制buffer res.set({ 'Content-Type': 'application/pdf', 'Content-Length': pdf.data.length }); res.send(pdf.data); }) .catch((error) => res.status(400).send('Error: ' + error)); });
4. React前端GET请求
保持现有逻辑即可,后端已返回正确的二进制Blob:
axios.get(`url/file/${id}`, { responseType: 'blob' }) .then((res) => { setPdfData(URL.createObjectURL(res.data)); }) .catch((error) => console.log(error));
验证步骤
- 上传PDF后,检查MongoDB中
data字段是否为二进制类型(而非字符串或数组)。 - 发起GET请求时,查看浏览器网络面板,确认响应类型为
application/pdf,响应内容为原始二进制数据。 - 确保iframe展示时的
src指向生成的ObjectURL:
<iframe src={pdfData} width="100%" height="600px" title="PDF Viewer" />
内容的提问来源于stack exchange,提问作者Kaustubh Kadu
相关产品推荐
相关产品推荐

