本地正常的图片上传API部署Vercel失效,求跨环境兼容方案
解决Next.js图片上传API在Vercel部署后失效的问题
问题原因
- Vercel的无服务器函数运行在临时容器中,不支持写入本地文件系统,所有写入的文件会在函数执行结束后被销毁,无法持久化存储。
public目录在Vercel构建完成后属于静态资源目录,处于只读状态,无法向其中写入文件。- 原代码缺少
writeFile的导入(import { writeFile } from 'fs/promises'),本地可能因环境兼容正常运行,但部署后会直接报错。
解决方案
使用Vercel官方提供的Blob存储服务来持久化上传的文件,同时兼容本地开发环境(本地仍写入文件系统)。
步骤1:安装依赖
npm install @vercel/blob
步骤2:修改API路由代码
import { NextRequest, NextResponse } from 'next/server' import crypto from 'crypto' import { writeFile, mkdirSync, existsSync } from 'fs/promises' import { put } from '@vercel/blob' export async function POST(request) { const data = await request.formData() const file = data.get('image') if (!file) { return NextResponse.json({ success: false, message: '未上传文件' }, { status: 400 }) } const bytes = await file.arrayBuffer() const buffer = Buffer.from(bytes) // 生成唯一文件名 const hash = crypto.createHash('md5').update(buffer).digest('hex') const extension = file.name.split('.').pop() const uniqueFilename = `${hash}.${extension}` let fileUrl = '' if (process.env.NODE_ENV === 'production') { // Vercel生产环境:使用Blob存储 const blob = await put(uniqueFilename, buffer, { access: 'public', // 设置为公开访问 }) fileUrl = blob.url } else { // 本地开发环境:写入本地文件系统 const uploadDir = './public/upload' // 确保上传目录存在 if (!existsSync(uploadDir)) { mkdirSync(uploadDir, { recursive: true }) } const path = `${uploadDir}/${uniqueFilename}` await writeFile(path, buffer) fileUrl = `/upload/${uniqueFilename}` } return NextResponse.json({ success: true, data: fileUrl }) }
步骤3:配置Vercel环境变量
在Vercel项目控制台的「Settings → Environment Variables」中添加:
- 变量名:
BLOB_READ_WRITE_TOKEN - 变量值:从Vercel Blob控制台获取的读写令牌
关键说明
- 本地开发时,上传的文件会保存在
public/upload目录下,可通过http://localhost:3000/upload/[文件名]访问。 - Vercel生产环境中,文件会存储在Vercel Blob中,返回的URL是Blob的公开访问地址,无需担心文件丢失。
- 如果不想区分环境,也可以统一使用Vercel Blob,本地开发时同样需要配置
BLOB_READ_WRITE_TOKEN环境变量。
内容的提问来源于stack exchange,提问作者ayanonize
相关产品推荐
相关产品推荐

