如何在Next.js中访问上传到public文件夹的文件?
问题根因
Next.js 生产模式(npm run start 启动)的静态资源读取逻辑和开发模式(npm run dev)有本质区别:
- 开发模式下 Next.js 会实时监听
public文件夹的变动,新增的文件会被即时识别可访问 - 生产模式下,
public文件夹的内容仅在执行npm run build构建阶段被扫描录入静态资源映射表,构建完成后运行时新增到public的文件不会被服务识别,哪怕物理文件确实存在也无法通过公开URL访问,这是Next.js生产模式的设计特性,不是Bug。
可行解决方案
方案1:使用独立的静态文件存储服务(生产环境首选)
把用户上传的文件存在独立的对象存储服务(比如本地部署的MinIO、云服务商的OSS/COS等),上传成功后直接返回存储服务的访问URL即可。该方案完全避开Next.js静态资源的逻辑限制,同时也能避免后续重新部署项目时,public 目录的上传文件被新版本覆盖丢失的问题。
方案2:自定义接口代理读取本地文件
如果必须存储在项目所在的服务器本地,不要存到 public 文件夹,单独新建一个存储目录(比如项目根目录下的 uploads 文件夹),然后写一个API接口读取目录下的文件返回给前端。
Pages Router 示例代码(/pages/api/file/[filename].ts):
import fs from 'fs' import path from 'path' import { NextApiRequest, NextApiResponse } from 'next' export default function handler(req: NextApiRequest, res: NextApiResponse) { const { filename } = req.query const filePath = path.join(process.cwd(), 'uploads', filename as string) if (!fs.existsSync(filePath)) { return res.status(404).send('File not found') } const fileBuffer = fs.readFileSync(filePath) // 可根据文件后缀动态调整Content-Type res.setHeader('Content-Type', 'image/jpeg') res.send(fileBuffer) }
配置完成后通过路径 /api/file/[目标文件名] 即可正常访问上传的文件。
注意事项
不要把用户上传的文件持久化存在 public 目录,哪怕临时调整配置解决了访问问题,后续每次重新构建部署项目时,新打包的 public 目录会覆盖原有目录,所有历史上传的文件都会丢失,属于生产环境严重隐患。
内容的提问来源于stack exchange,提问作者SonickSeven
相关产品推荐
相关产品推荐

