我正在开发一个 Next.js 14 应用程序,我需要使用存储在公共文件夹中的图像。虽然图像在客户端正确加载,但在尝试从服务器操作中的公用文件夹读取图像文件时遇到问题。我是 nextjs 的新手,可能会在这里监督一些明显的事情......
项目设置
客户端代码(工作) 以下代码在登陆页面上正确加载 LandingPageImage.png:
<Box
component="img"
sx={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
objectFit: "cover",
}}
alt="alt"
src="/LandingPageImage.png"
/>
服务器端代码(部署在 Vercel 上时不工作,在本地工作)
console.log(fs.readdirSync("./"));
const image = new ImageRun({
data: fs.readFileSync("./Public/Icon.png"),
transformation: {
width: 140,
height: 50,
},
});
我注意到,在本地开发中,我也不允许使用下一个通过使用“/”作为路径来引用公共文件夹中的静态服务器文件的快捷方式。因此,当使用 fs 时,我必须将其写为“./Public/Icon.png”,它在本地开发中工作。
Vercel 日志
从 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']
没有公共文件夹?它在 .next 中吗?
最终评论
基本上,公共文件夹中的资源可以从客户端访问,但是当尝试通过 fs 使用服务器操作获取它们时,公共文件夹似乎根本不存在。至少在服务器端。
我是否必须使用 nextjs 以不同的方式存储服务器资源?
潜在的解决方案
我读到了为图像创建指定 API 的选项,以便服务器操作可以调用该端点来获取图像。或者,可以从“https://myapp.vercel.app/Icon.png”获取图像。这两种解决方案都感觉有点拼凑,我会假设 Nextjs 涵盖了这种情况。
这个方法你试过吗?
const dir = path.join(process.cwd(), "path_which_you_want");
const content = fs.readFileSync(dir);