Nextjs文件上传(原生、multer)

519 阅读1分钟

前言

学习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,
  }
}

文章若有错误请在评论区指出