前言
学习nextjs,写了一个可以发布博客的demo,最近想要加上博客封面图上传功能,开始实现之后,发现对于nextjs新用户来说不是那么容易,查了一些资料和自己成功实践之后,把上传文件功能部分知识点记录并分享一下。
一、原生上传(无任何第三方包导入)
在尝试进行接收页面请求接口传递的file文件的时候,如果将req定义为NextApiRequest会发现这个上面没有可以获取formData的方法。而如果将req定义为NextRequest,req上就存在formData这个方法。
NextApiRequest
api/upload.ts
import { NextApiRequest, NextApiResponse } from 'next';
export default function POST (req: NextApiRequest, res: NextApiResponse) {
console.log(req);
console.log(req.formData);
console.log(req.body);
// 会发现这里的formData和body都是undefined
}
NextRequest
api/upload.ts
import { NextRequest, NextResponse } from 'next/server';
import fs from 'fs';
import path from 'path';
export default async function POST (req: NextRequest) {
const formData = await req.formData();
const file: File | null = formData.get('file') as unknown as File;
if (!file) {
return NextResponse.json({
code: -1,
msg: '文件上传失败'
})
}
const fileName = file.originalname;
const bytes = await file.arrayBuffer();
const buffer = Buffer.from(bytes);
const uploadPath = path.join(process.cwd(), 'public/uploads', `${Date.now()}-${fileName}`);
await fs.writeFile(uploadPath, buffer);
return NextResponse.json({
code: 0,
msg: '文件上传成功',
})
}
二、使用multer
安装
npm install multer next-connect
api/upload.ts
import { NextApiRequest, NextApiResponse } from 'next';
import multer from 'multer';
import * as nc from 'next-connect';
import path from 'path';
const router = nc.createRouter();
const upload_path = path.join(process.cwd(), 'public/uploads');
const storage = multer.diskStorage({
destination: upload_path,
filename: (req, file, cb) => {
cb(null, `${Date.now()}-${file.originalname}`)
}
})
const upload = multer({
storage
})
router.use(upload.single('file') as any);
router.post(((req: NextApiRequest, res: NextApiResponse) => {
const file = (req as any).file;
if (!file) {
res.status(400).send({
code: -1,
msg: '文件上传失败',
})
}
const filePath = `/uploads/${file.filename}`;
res.status(200).send({
code: 0,
msg: '文件上传成功',
path: filePath
})
}) as any)
export default router.handler();
export const config = {
api: {
bodyParser: false,
}
}
文章若有错误请在评论区指出