You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用multer-s3无法上传大于1MB文件的问题及提速咨询

问题解决:multer-s3 大文件上传失败及提速方案

问题原由

你遇到的大文件(>1MB)上传时指定代码块不执行、无报错却返回201的问题,核心原因是原代码中异步处理的顺序错误:
在控制器里手动调用s3upload.single('file')后,没有等待multer的异步上传流程完成,就直接执行了res.status(201).send("Success")。小文件因为处理速度快,能在响应发送前完成上传;但大文件处理耗时更长,响应已经提前发送,导致multer的回调函数根本没机会执行。

原代码问题点

import { Request, Response } from 'express';
import { v4 as uuidv4 } from 'uuid';
import multer from 'multer';
import multerS3 from "multer-s3"
import s3 from "../config/amazons3"

const uploadController = { 
    transferFile: async (req, res) => {
        try {
            const s3upload = multer({
                storage: multerS3({
                    s3: s3,
                    acl: 'public-read',
                    bucket: 'filetransferawsbucket1',
                    metadata: (req, file, cb) => {
                        cb(null, {fieldName: file.fieldname})
                    },
                    key: (req, file, cb) => {
                        try {
                            console.log("File", file)
                            const key: string = `medium_zip_file_${uuidv4()}`
                            cb(null, key)
                        } catch (error) {
                            cb(error)
                        }
                    }
                }),
                limits: {
                    fileSize: 5 * 1024 * 1024 * 1024,
                    fieldSize: 52428800
                },
                fileFilter: (req, file, cb) => {
                    if (file.mimetype === 'application/zip') {
                      cb(null, true)
                    } else {
                      cb(new Error('Invalid file type. Only zip files are allowed.'))
                    }
                },
            })

            console.log('Before Multer Middleware')

            // 大文件上传时,这个异步回调还没执行,响应就已经发送了
            s3upload.single('file')(req, res, (err) => {
                console.log('After Multer Middleware')
                if (err) {
                    console.log('Multer error:', err)
                    return res.status(500).json({ error: "Error processing file upload" })
                }
            })

            // 直接返回响应,打断了multer的异步上传流程
            res.status(201).send("Success")

        } catch (error) {
            console.log("TRANSFER FILE ERROR", error)
            res.status(500).json({ error: "Error transferring file" })
        }
    }
}

未执行的代码块:

s3upload.single('file')(req, res, (err) => {
    console.log('After Multer Middleware')
    if (err) {
        console.log('Multer error:', err)
        return res.status(500).json({ error: "Error processing file upload" })
    }
})

已验证的解决方法:调整中间件位置

把multer-s3的中间件直接挂载到路由上,让Express的中间件流程自动处理异步顺序,确保文件上传完成后再进入控制器逻辑。

修改后的代码

uploadRouter.ts

import express from "express"
import uploadController, { s3upload } from "../controllers/uploadContoller"

const router = express.Router()

// 将s3upload中间件放在路由定义中,由Express管理执行顺序
router.post("/transferFile", s3upload.single("file"), uploadController.transferFile)

export default router

uploadController.ts

import { Request, Response } from 'express';
import { TransferModel } from "../models/transferModel";
import { v4 as uuidv4 } from 'uuid';
import multer from 'multer';
import multerS3 from "multer-s3"
import s3 from "../config/amazons3"

interface IUploadContoller {
    transferFile: (req: Request, res: Response) => Promise<void>
    transferFileBusBoy?: (req: Request, res: Response) => Promise<void>
}

// 抽离multer配置,作为全局可复用的中间件
export const s3upload = multer({
    storage: multerS3({
        s3: s3,
        acl: 'public-read',
        bucket: 'filetransferawsbucket1',
        metadata: (req, file, cb) => {
            cb(null, {fieldName: file.fieldname})
        },
        key: (req, file, cb) => {
            try {
                console.log("***FILE***", file)
                const key: string = `medium_zip_file_${uuidv4()}`
                cb(null, key)
            } catch (error) {
                cb(error)
            }
        }
    }),
    limits: {
        fileSize: 5 * 1024 * 1024 * 1024,
        fieldSize: 5 * 1024 * 1024 * 1024, 
    },
    fileFilter: (req, file, cb) => {
        if (file.mimetype === 'application/zip') {
          cb(null, true)
        } else {
          cb(new Error('Invalid file type. Only zip files are allowed.'))
        }
    },
})

const uploadController: IUploadContoller = { 
    transferFile: async (req: Request, res: Response) => {
        try {
            console.log('Before Multer Middleware')
            res.status(201).send("Success")
        } catch (error) {
            console.log("TRANSFER FILE ERROR", error)
            res.status(500).json({ error: "Error transferring file" })
        }
    },
}

export default uploadController

大文件上传提速建议

目前你已经能上传1GB文件但耗时5分钟,可以试试这些优化方向:

  • 启用S3分片上传
    在AWS SDK配置中开启分片上传,让大文件自动拆分后并行传输:

    // 在../config/amazons3中修改S3客户端配置
    import { S3Client } from "@aws-sdk/client-s3";
    const s3 = new S3Client({
      region: "你的存储桶区域",
      multipartUploadThreshold: 5 * 1024 * 1024, // 大于5MB自动分片
      multipartUploadSize: 5 * 1024 * 1024, // 每个分片大小
      maxAttempts: 3, // 分片上传失败重试次数
    });
    
  • 对齐服务器与S3区域
    确保你的Node.js服务器和S3存储桶在同一AWS区域,跨区域传输会大幅增加延迟和耗时。

  • 前端分片上传
    在前端把大文件分成10MB-50MB的小分片,并行上传到S3后再合并,既能利用多线程提升速度,还支持断点续传。

  • 优化AWS SDK超时设置
    增大超时时间避免大文件上传中途断开:

    const s3 = new S3Client({
      region: "你的存储桶区域",
      requestTimeout: 300000, // 5分钟请求超时
      connectionTimeout: 60000, // 1分钟连接超时
    });
    
  • 文件压缩预处理
    对zip文件在前端用更高压缩率的算法二次压缩,减小文件体积后再上传,从根源减少传输时间。

内容的提问来源于stack exchange,提问作者firefly1095

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:54:56