如何将react-pdf生成的PDF blob上传至S3,遇到Unsupported body payload报错如何解决
错误根因
你直接将File二进制对象放在JSON请求体中提交,axios默认会将请求转为application/json格式,二进制文件无法被正确JSON序列化,后端拿到的file字段只是个无有效二进制内容的普通JS对象,因此S3上传时无法识别合法的负载内容。
修复步骤
1. 前端请求改造
改用FormData封装文件和参数,axios会自动处理二进制传输逻辑:
const fileName = Date.now().toString() + ".pdf"; // 构造File对象时显式指定文件类型 const file = new File([blob], fileName, { type: "application/pdf" }); // 用FormData封装所有请求参数 const formData = new FormData(); formData.append("fileName", fileName); formData.append("file", file); axios.post("api/upload-poster", formData, { headers: { "Content-Type": "multipart/form-data", }, }).then(({ data }) => console.log(data));
2. 后端接口改造
Next.js默认会解析请求体,需要先关闭默认解析逻辑,再使用formidable解析multipart/form-data格式的请求:
- 先安装依赖:
npm install formidable - 接口代码修改如下:
// 关闭Next.js默认的body解析 export const config = { api: { bodyParser: false, }, }; import formidable from "formidable"; import S3 from "aws-sdk/clients/s3"; const s3 = new S3({ // 替换为你自己的S3配置 accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, region: process.env.AWS_REGION, }); export default async function handler(req, res) { const form = formidable({}); // 解析表单提交的内容 const [fields, files] = await form.parse(req); const fileName = fields.fileName[0]; const pdfFile = files.file[0]; const params = { Bucket: "my-bucket-name", Key: fileName, // 读取临时文件流作为上传内容 Body: require("fs").createReadStream(pdfFile.filepath), // 注意AWS SDK参数为大写开头的ContentType,你之前的小写参数会失效 ContentType: "application/pdf", }; const uploaded = await s3.upload(params).promise(); res.status(200).json({ uploaded }); }
可选轻量方案(仅适合小体积PDF)
如果不想引入formidable依赖,可在前端将Blob转为Base64字符串后用JSON传输,后端解码为Buffer再上传:
- 前端转换代码:
const reader = new FileReader(); reader.readAsDataURL(blob); reader.onloadend = () => { const base64Pdf = reader.result; // 把base64Pdf和fileName放在普通JSON里提交即可 }
- 后端直接将Base64转Buffer传给S3的Body字段:
Body: Buffer.from(file.replace(/^data:application\/pdf;base64,/, ""), "base64")
内容的提问来源于stack exchange,提问作者Karolis
相关产品推荐
相关产品推荐

