Strapi通过S3上传大文件的临时存储与内存问题咨询
问题描述
- 环境:Ubuntu v24.10服务器,Strapi v5.1.1,Nginx 1.26,S3存储媒体文件,MySQL数据库,主机为DigitalOcean Droplet
- 核心问题:本地开发环境可正常上传1.85GB文件,但生产环境上传大文件时报
ENOSPC: no space left on device, write错误,目标需支持10GB文件上传 - 已完成的配置调整:
- Strapi端:修改
config/middlewares.ts、config/plugins.ts,设置文件大小限制为10GB、延长请求超时 - 迁移至Droplet,规避Cloudflare 500MB文件上传限制
- Nginx端:设置
client_max_body_size 10240M、关闭请求缓冲、延长超时参数 - 调整sysctl参数,增大inotify相关限制
- 确认服务器磁盘剩余19G空间充足
- Strapi端:修改
- 后续排查发现:
- 本地调整文件大小限制后恢复正常,但生产环境问题依旧
- Strapi默认将文件写入系统
/tmp分区而非项目.tmp目录,原/tmp仅984MB;扩容至11G后,上传时内存占用飙升(2G内存服务器上传1.5GB文件会死机),升级至4G内存可成功上传1.5GB文件,但无法支持10GB文件
解决方案与优化建议
1. Strapi上传至S3是否必须写入/tmp和内存?
默认流程下,Strapi会先将完整文件写入系统临时目录(/tmp),再读取文件内容上传到S3,同时文件数据会加载到内存中——这是大文件上传时内存、磁盘占用飙升的核心原因,但这个行为并非强制不可改。
你可以通过以下方式修改临时文件存储路径,规避系统默认小容量/tmp分区的限制:
- 在Strapi运行的环境变量中设置
TMPDIR,指定项目目录下的.tmp文件夹作为临时存储路径,示例:export TMPDIR=/path/to/your/strapi/project/.tmp - 确保该目录有足够磁盘空间,且Strapi进程拥有读写权限。
2. 如何通过@strapi/provider-upload-aws-s3插件优化大文件上传?
即便已配置分片上传,仍可通过插件的进阶配置实现流式上传(无需先写入本地临时文件,直接将请求流传输到S3),彻底解决磁盘和内存占用问题:
配置流式上传
在config/plugins.ts中修改S3插件配置,启用流式上传并调整分片参数:
export default ({ env }) => ({ upload: { config: { provider: 'aws-s3', providerOptions: { accessKeyId: env('AWS_ACCESS_KEY_ID'), secretAccessKey: env('AWS_ACCESS_SECRET'), region: env('AWS_REGION'), params: { Bucket: env('AWS_BUCKET'), }, // 启用流式上传,跳过本地临时文件写入 stream: true, // 配置分片上传参数,适配大文件 partSize: 10 * 1024 * 1024, // 单分片大小设为10MB queueSize: 4, // 并发上传的分片数量 }, }, }, });
配合Strapi中间件调整
确保config/middlewares.ts中的body-parser配置支持流式处理,避免缓存整个请求体到内存:
export default [ // ...其他中间件配置 { name: 'strapi::body', config: { jsonLimit: '10gb', formLimit: '10gb', textLimit: '10gb', formidable: { maxFileSize: 10 * 1024 * 1024 * 1024, // 10GB文件上限 keepExtensions: true, uploadDir: '/path/to/your/strapi/project/.tmp', // 可选:若仍需临时文件则指定 multiples: true, // 关键配置:启用流式解析,不缓存文件到内存 fileWriteStreamHandler: (file) => { // 启用S3流式上传后,插件会自动对接请求流,此处无需额外处理 }, }, }, }, ];
额外优化建议
- Nginx配置强化:确保Nginx完全禁用请求缓冲,避免Nginx先缓存整个文件到磁盘或内存:
location / { proxy_pass http://localhost:1337; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 禁用请求缓冲 proxy_request_buffering off; proxy_buffering off; # 延长超时时间适配大文件上传 proxy_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; client_max_body_size 10240M; } - 系统级优化(可选):若仍需使用临时文件,可挂载大磁盘分区到自定义临时目录;若启用流式上传,Node.js内存限制调整(如
NODE_OPTIONS="--max-old-space-size=4096")可忽略。
内容的提问来源于stack exchange,提问作者slownames
相关产品推荐
相关产品推荐

