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

POST请求嵌入Base64格式PDF上传后保存为空白文件问题求助

问题根因

  • 前端使用readAsBinaryString读取得到的原始二进制字符串无法直接通过JSON序列化传输:JSON默认采用UTF-8编码,二进制流中大量非UTF-8兼容字节会被转义,导致传输后的二进制数据完全损坏,这是文件体积变大、PDF打开空白的核心原因。
  • 服务端直接将收到的字符串写入文件,没有做对应的编码转换,写入的内容不是合法的PDF二进制流。

现有Base64方案修复

你原本的思路是将文件转Base64嵌入JSON,只要补全编码、解码逻辑即可正常运行:

前端代码修改

将文件读取方式改为直接生成Base64格式的DataURL:

async function post(endpoint){
    let CV = document.getElementById("upfile").files[0];
    var reader = new FileReader();
    reader.onload = (readerEvt)=>{
        const base64CV = readerEvt.target.result;
        let xhr = new XMLHttpRequest();
        let object = {
            name: document.getElementById("ecaName").value,
            email: document.getElementById("ecaEmail").value,
            phone: document.getElementById("ecaTel").value,
            class: document.getElementById("ecaClass").value,
            institute: document.getElementById("ecaInstitute").value,
            paragraph:{
                experience: document.getElementById("ecaExp").value,
                why: document.getElementById("ecaWhyPart").value,
                changes: document.getElementById("ecaWhatChanges").value,
            },
            CV: base64CV,
        }
        xhr.open("POST", `http://localhost:8080/apply/internship/${endpoint}`,true);
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.send(JSON.stringify(object));
    };
    // 替换原有readAsBinaryString方法
    reader.readAsDataURL(CV);
}

后端代码修改

收到Base64内容后先解码为二进制Buffer再写入文件:

app.post('/apply/internship/econoxe', async (req, res)=>{
    res.sendStatus(200);
    let base64CV = req.body.CV;
    // 移除Base64前缀标识
    const pureBase64 = base64CV.replace(/^data:.+;base64,/, '');
    // 解码为PDF二进制Buffer
    const pdfBuffer = Buffer.from(pureBase64, 'base64');
    fs.writeFileSync(path.join(__dirname,`../CV/${req.body.email}.pdf`), pdfBuffer);
    console.log(req.body);
})

同路由传输JSON+文件的更优方案

multipart/form-data方案不需要单独配置路由,比Base64传输体积小30%左右,性能更高,实现方式如下:

  1. 先安装依赖:npm install multer
  2. 前端代码修改,使用FormData承载所有参数和文件:
async function post(endpoint){
    let CV = document.getElementById("upfile").files[0];
    const formData = new FormData();
    // 填充普通字段
    formData.append('name', document.getElementById("ecaName").value);
    formData.append('email', document.getElementById("ecaEmail").value);
    formData.append('phone', document.getElementById("ecaTel").value);
    formData.append('class', document.getElementById("ecaClass").value);
    formData.append('institute', document.getElementById("ecaInstitute").value);
    // 嵌套对象转为JSON字符串传输
    formData.append('paragraph', JSON.stringify({
        experience: document.getElementById("ecaExp").value,
        why: document.getElementById("ecaWhyPart").value,
        changes: document.getElementById("ecaWhatChanges").value,
    }));
    // 填充PDF文件
    formData.append('CV', CV);

    let xhr = new XMLHttpRequest();
    xhr.open("POST", `http://localhost:8080/apply/internship/${endpoint}`,true);
    // 不要手动设置Content-Type,浏览器会自动生成带boundary的请求头
    xhr.send(formData);
}
  1. 后端代码修改,使用multer中间件同时解析表单字段和文件:
const multer = require('multer');
// 配置文件存储规则
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, path.join(__dirname, '../CV/'))
  },
  filename: function (req, file, cb) {
    cb(null, `${req.body.email}.pdf`)
  }
})
const upload = multer({ storage: storage })

// 原路由完全不需要修改,添加中间件即可同时处理字段和文件
app.post('/apply/internship/econoxe', upload.single('CV'), async (req, res)=>{
    res.sendStatus(200);
    // 普通字段全部在req.body中,嵌套对象手动解析即可
    const paragraph = JSON.parse(req.body.paragraph);
    // 文件已自动写入配置的存储路径,无需手动调用fs写入
    console.log('请求参数', req.body, '文件信息', req.file);
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 16:18:01