You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 00:42:01