NextJS API路由接收上传文件 调用XLSX.read解析失败如何解决
问题根因
你当前的代码失效的核心原因是:Next.js Pages Router的API路由默认开启了bodyParser,会自动解析入站请求的请求体,你拿到的req.body已经是经过解析的结构化数据,不是原始的文件二进制流,因此无法被XLSX识别。
以下是两种场景下的可行解决方案:
方案1:针对Pages Router(对应你当前用的pages/api/目录结构)
- 先安装formidable用来解析multipart/form-data类型的文件上传请求:
npm install formidable xlsx # TypeScript项目额外安装类型声明 npm install -D @types/formidable
- 在API路由文件中关闭默认的bodyParser配置:
export const config = { api: { bodyParser: false, } };
- 改写handler逻辑,用formidable解析上传文件后再交给XLSX处理:
import XLSX from "xlsx"; import formidable from "formidable"; import fs from "fs"; export default async function handler(req, res) { const form = formidable({}); let arr; try { // 解析请求中的表单数据 const [fields, files] = await form.parse(req); // 拿到上传的文件对象,formidable返回的files是数组,取第一个元素 const excelFile = files.file[0]; // 读取文件的二进制Buffer const fileBuffer = fs.readFileSync(excelFile.filepath); // 直接用Buffer解析Excel const workbook = XLSX.read(fileBuffer, { type: "buffer" }); const sheet = workbook.Sheets[workbook.SheetNames[0]]; arr = XLSX.utils.sheet_to_json(sheet); } catch (e) { console.error("Error while reading the excel file", e); return res.status(500).json({ err: "文件解析失败" }); } res.status(200).json(arr); }
方案2:针对App Router(对应app/api/目录结构)
App Router的路由处理不需要关闭bodyParser,可直接调用内置的formData()方法解析上传文件:
// app/api/importExcel/route.js import XLSX from "xlsx"; import { NextResponse } from "next/server"; export async function POST(req) { try { const formData = await req.formData(); const file = formData.get("file"); // 转成ArrayBuffer const buffer = await file.arrayBuffer(); const workbook = XLSX.read(buffer, { type: "array" }); const sheet = workbook.Sheets[workbook.SheetNames[0]]; const arr = XLSX.utils.sheet_to_json(sheet); return NextResponse.json(arr); } catch (e) { console.error("解析失败", e); return NextResponse.json({ err: "文件解析失败" }, { status: 500 }); } }
前端注意事项
使用axios发送FormData时,不要手动设置Content-Type: multipart/form-data请求头,axios会自动生成带正确boundary标识的请求头,手动设置会导致服务端无法识别文件边界,解析失败。
内容的提问来源于stack exchange,提问作者Istvan Nagy
相关产品推荐
相关产品推荐

