Strapi上传长文件名文件触发ENAMETOOLONG错误问题咨询
系统信息
- Strapi版本:4.1.12
- 操作系统:MacOS
- 数据库:Postgres
- Node版本:16.15.1
- NPM版本:8.11.0
- Yarn版本:1.22.11
问题现象
尝试上传文件名较长的文件时,抛出如下系统错误:error: ENAMETOOLONG: name too long
可稳定触发报错的文件名如下:
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book here a.pdf
错误根本原因
该错误是操作系统文件系统层面抛出的系统级错误,和Strapi业务逻辑、Postgres数据库无直接关联:
- MacOS默认使用的APFS/HFS+文件系统有明确长度限制:单个文件名(不含路径前缀)最大长度为255字节,文件全路径(从根目录到文件名的完整字符串)最大长度通常为1024字节。上述触发报错的文件名算上
.pdf后缀字符数已经超过230,而Strapi在存储原文件、生成不同尺寸缩略图时,会自动给文件名追加随机防重哈希、尺寸标识后缀(例如_750x1200、8位随机字符串),最终生成的实际存储文件名长度会直接超出单文件255字节的上限,触发报错。 - 如果自定义过Strapi本地文件存储路径,且路径本身层级较深、前缀字符串较长,也可能在文件名本身未超255字节的情况下,提前触发全路径长度限制报错。
排查解决方向
- 先核对存储路径长度:查看Strapi默认配置的
public/uploads目录全路径长度,如果路径本身长度已经超过700字节,先调整存储目录到磁盘更浅层级,例如直接在磁盘根目录创建专属存储文件夹挂载给Strapi,减少路径前缀占用的长度空间。 - 添加上传文件名截断逻辑:在Strapi上传模块的
beforeUpload生命周期钩子中添加自定义处理逻辑,保留文件后缀的前提下,对原文件名做长度截断,给后续系统自动追加的哈希、缩略图后缀预留足够长度空间。参考实现代码如下:
// 文件路径:src/extensions/upload/extensions/content-types/file/lifecycles.js module.exports = { async beforeUpload(event) { const { file } = event.params; const dotIndex = file.name.lastIndexOf('.'); // 兼容无后缀文件场景 const ext = dotIndex > -1 ? file.name.substring(dotIndex) : ''; const nameWithoutExt = dotIndex > -1 ? file.name.substring(0, dotIndex) : file.name; // 按字节长度截断文件名(不含后缀)到180字节,预留75字节给系统自动生成的后缀 const byteLength = Buffer.byteLength(nameWithoutExt, 'utf8'); if (byteLength > 180) { file.name = Buffer.from(nameWithoutExt, 'utf8').slice(0, 180).toString('utf8').replace(/\uFFFD/g, '') + ext; } } }
- 截断逻辑注意事项:中文、全角符号等非ASCII字符单个会占用2-3字节,不要直接按字符数截断,避免切到字符中间产生乱码;上述代码用Buffer按字节截断后,会自动清理截断产生的无效乱码字符。
- 如果使用第三方云存储插件做文件存储,需要同步核对对应云服务商的对象存储文件名长度限制,多数对象存储单文件名长度上限为254字符,同样需要在上传前做统一截断处理。
内容的提问来源于stack exchange,提问作者Jay Sojitra
相关产品推荐
相关产品推荐

