You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MongoDB中上传并获取PDF?解决Blob文件损坏问题

问题分析与解决方案

核心问题点

  1. 前端POST请求手动设置Content-Type导致解析错误:手动指定multipart/form-data会丢失boundary信息,Axios无法正确处理FormData结构。
  2. 后端POST路由读取文件方式冗余易出错:multer上传的文件本身提供buffer属性,无需通过fs.readFileSync读取本地文件路径。
  3. 后端GET路由错误返回JSON格式:将PDF二进制数据转为JSON返回时,会破坏原始二进制结构,导致前端生成的Blob损坏。
  4. 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));

验证步骤

  1. 上传PDF后,检查MongoDB中data字段是否为二进制类型(而非字符串或数组)。
  2. 发起GET请求时,查看浏览器网络面板,确认响应类型为application/pdf,响应内容为原始二进制数据。
  3. 确保iframe展示时的src指向生成的ObjectURL:
<iframe src={pdfData} width="100%" height="600px" title="PDF Viewer" />

内容的提问来源于stack exchange,提问作者Kaustubh Kadu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:33:26