Vercel部署环境下如何在API路由中正确读取文件
解决Vercel部署后Nuxt API无法读取本地文件夹的问题
问题原因
Vercel的无服务器函数环境中,process.cwd()指向的是函数执行的临时工作目录,而非项目根目录;同时未明确标记的本地文件夹不会被打包进函数部署包,导致fs.readdirSync找不到目标目录。
正确实现步骤
1. 配置Nitro将素材目录标记为服务器资产
在nuxt.config.ts中添加Nitro配置,将characters目录设为非公开的服务器资产,确保部署时该目录会被打包到函数环境中:
export default defineNuxtConfig({ nitro: { publicAssets: [ { dir: './characters', serve: false, // 禁止公开访问该目录,符合隐私需求 maxAge: 31536000 // 高频访问场景建议设置较长缓存时长 } ] } })
2. 修改API路由使用Nitro存储读取目录
利用Nitro的useStorage可以读取整个目录的文件列表,替代原生fs模块。修改server/api/read-characters.ts代码如下:
export default defineEventHandler(async (event) => { // 获取characters目录下的所有文件路径(带前缀) const fileKeys = await useStorage('assets:').getKeys('characters/') // 提取纯文件名,去掉"characters/"前缀 const files = fileKeys.map(key => key.split('/').pop()) return files })
如果需要读取单个文件内容(用于图片叠加计算),可以直接通过存储路径获取:
// 示例:读取指定素材文件的Buffer const getCharacterAsset = async (filename) => { return await useStorage('assets:characters/').getItem(filename) }
3. 针对高频访问与大文件的优化
- 缓存文件列表:将文件列表缓存到内存,避免每次请求都遍历目录。可以用Nitro内置缓存:
const cachedFiles = await useCache().get('characters:filelist') if (!cachedFiles) { const fileKeys = await useStorage('assets:').getKeys('characters/') const files = fileKeys.map(key => key.split('/').pop()) await useCache().set('characters:filelist', files, { ttl: 3600 }) // 缓存1小时 return files } return cachedFiles - 按需加载文件:仅在需要处理某张素材时才读取对应文件,避免一次性加载全部50MB+的文件,节省内存与带宽。
- 使用Edge Functions:如果访问频率极高,可将API路由改为Edge Function(在文件名后加
.edge.ts),进一步降低响应延迟。
注意事项
- 确保
characters目录未被.gitignore排除,否则部署时Vercel不会上传该目录。 - 若素材文件更新,需重新部署项目以同步最新文件到服务器资产中。
- 二进制文件(如图片)通过
useStorage读取时会直接返回Buffer,可直接用于后续图片处理逻辑。
内容的提问来源于stack exchange,提问作者Felix Ranesberger
相关产品推荐
相关产品推荐

