Next.js 14服务器端无法读取Public目录文件问题求助
Next.js 14服务器端操作无法读取public文件夹图片的问题
项目配置
- Next.js版本:14
- 托管平台:Vercel
- UI库:MUI Image
- 文件位置:
/public/LandingPageImage.png(客户端组件中正常加载)/public/Icon.png(服务器端操作中读取失败)
客户端正常工作代码
以下代码可在登录页正确加载LandingPageImage.png:
<Box component="img" sx={{ position: "absolute", top: 0, left: 0, width: "100%", height: "100%", objectFit: "cover", }} alt="alt" src="/LandingPageImage.png" />
服务器端代码(本地正常,Vercel部署后失效)
本地开发时用相对路径可读取,但部署到Vercel后报错:
console.log(fs.readdirSync("./")); const image = new ImageRun({ data: fs.readFileSync("./Public/Icon.png"), transformation: { width: 140, height: 50, }, });
Vercel错误日志
出现文件未找到错误:
Error: ENOENT: no such file or directory, open './Public/Icon.png' at Object.openSync (node:fs:573:18) at Object.readFileSync (node:fs:452:35) at w (/var/task/.next/server/app/workflow/[projectId]/[protocolId]/page.js:1:25191) at c (/var/task/.next/server/app/workflow/[projectId]/[protocolId]/page.js:1:26376) at async a (/var/task/.next/server/app/workflow/[projectId]/[protocolId]/page.js:1:23033) at async /var/task/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:16:418 at async rP (/var/task/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:15:7978) at async r5 (/var/task/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:18:1139) at async es (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:16:26320) at async ei.responseCache.get.routeKind (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:17:1026) { errno: -2, code: 'ENOENT', syscall: 'open', path: './Public/Icon.png', digest: '3899936968' }
调试尝试与结果
通过打印目录结构查看文件位置:
console.log("./ ", fs.readdirSync("./")); console.log("/ ", fs.readdirSync("/")); console.log("../ ", fs.readdirSync("../")); console.log("../../ ", fs.readdirSync("../../"));
输出结果:
../../ ['THIRD-PARTY-LICENSES.txt', 'bin', 'boot', 'dev', 'etc', 'home', 'lambda-entrypoint.sh', 'lib', 'lib64', 'local', 'media', 'mnt', 'opt', 'proc', 'root', 'run', 'sbin', 'srv', 'sys', 'tmp', 'usr', 'var'] ../ ['adm', 'cache', 'db', 'empty', 'ftp', 'games', 'kerberos', 'lang', 'lib', 'local', 'lock', 'log', 'mail', 'nis', 'opt', 'preserve', 'rapid', 'run', 'runtime', 'spool', 'task', 'telemetry', 'tmp', 'tracer', 'yp'] / ['THIRD-PARTY-LICENSES.txt', 'bin', 'boot', 'dev', 'etc', 'home', 'lambda-entrypoint.sh', 'lib', 'lib64', 'local', 'media', 'mnt', 'opt', 'proc', 'root', 'run', 'sbin', 'srv', 'sys', 'tmp', 'usr', 'var'] ./ ['.next', '___next_launcher.cjs', 'node_modules', 'package.json']
问题总结
public目录中的资产可通过客户端URL正常访问,但服务器端用fs读取时,部署环境中找不到对应的文件目录。核心原因是本地与部署环境的工作目录差异、文件名大小写敏感问题。
正确解决方案
1. 使用绝对路径构建文件地址
服务器端读取文件时,必须基于项目根目录构建绝对路径,避免相对路径在不同环境下的差异。借助process.cwd()获取项目根目录,结合path.join拼接路径:
import fs from 'fs'; import path from 'path'; // 构建绝对路径,注意public是小写 const iconPath = path.join(process.cwd(), 'public', 'Icon.png'); const image = new ImageRun({ data: fs.readFileSync(iconPath), transformation: { width: 140, height: 50, }, });
2. 注意文件名大小写
Linux环境(Vercel使用)对文件名大小写敏感,必须保证代码中的路径与实际文件夹名一致(默认是public小写,不是Public)。本地Windows/macOS可能大小写不敏感,但部署后会报错。
原理说明
- 客户端用
/LandingPageImage.png是访问静态资源URL,Next.js会自动映射到public文件夹下的文件。 - 服务器端
fs读取的是文件系统路径,本地开发时工作目录是项目根目录,直接用./public/xxx可行,但Vercel部署后工作目录是/var/task,必须用process.cwd()获取项目根目录才能正确找到public文件夹。
内容的提问来源于stack exchange,提问作者Zuhlek
相关产品推荐
相关产品推荐

