【问题标题】:Upload to S3 using multer without a middleware function使用没有中间件功能的 multer 上传到 S3
【发布时间】:2021-03-02 04:30:21
【问题描述】:

我正在使用 multer 将媒体上传到我的 s3 存储桶。我正在使用 multer-s3 作为中间件来上传媒体,例如:

const upload = multer({
  storage: multerS3({
    s3: s3,
    bucket: myBucket,
    key: function (req, file, cb) {
      cb(null, new Date().getTime() + '_' + file.originalname)
    }
  })
});

并在路由中调用它:

router.post("/media",upload.single("media"))

这很好用。但是一个不适合我的场景是:假设我上传了一张图片,我想通过在上传之前调整它的大小来存储它的多个版本。我无法像普通函数一样调用上传函数。我想做类似的事情:

let thumbnail = myFunctionToReturnImageFile(req.file);
upload(thumbnail);

我知道我需要发送一些多部分/表单部分,但我无法找到解决方案。如果你给我推荐一个很棒的东西。

【问题讨论】:

  • 我正在尝试做类似的事情,我认为您可以使用 MemoryStorage,修改图像然后上传。
  • @JavierGuzmán 如果你能分享一些代码示例,我会很高兴
  • 我不能分享任何代码示例,因为我目前正在尝试类似的东西,但我还没有任何工作。但是,我使用此链接作为参考:medium.com/@olamilekan001/…

标签: node.js express amazon-s3 multer multer-s3


【解决方案1】:

选项 1 - 使用 multer-s3-transform 中间件通过文件转换处理 S3 上传,例如使用 sharp 调整图像大小。

const multer = require('multer')
const multerS3 = require('multer-s3-transform')
const sharp = require('sharp')
const AWS = require('aws-sdk')
const S3 = new AWS.S3({
    accessKeyId: ...,
    secretAccessKey: ...
})

const upload = multer({
  storage: multerS3({
    s3: S3,
    bucket: ...,
    shouldTransform: true,
    transforms: [
      {
        id: 'original',
        key: (req, file, cb) => cb(null, new Date().getTime() + '_' + req.file.originalname),
        transform: (req, file, cb) => cb(null, sharp().jpg())
      },
      {
        id: 'large',
        key: (req, file, cb) => cb(null, new Date().getTime() + '_large_' + req.file.originalname),
        transform: (req, file, cb) => cb(null, sharp().resize(1200, 900).jpg())
      },
      {
        id: 'small',
        key: (req, file, cb) => cb(null, new Date().getTime() + '_small_' + req.file.originalname),
        transform: (req, file, cb) => cb(null, sharp().resize(400, 300).jpg())
      }
    ]
  })
})

router.post('/media', upload.single('media'))

选项 2 - 如果您坚持手动操作,您可以使用纯 multer 处理传入文件,使用 sharp 调整大小,然后使用 @987654327 将每个调整大小的文件上传到 S3 @。

const multer = require('multer')
const sharp = require('sharp')
const AWS = require('aws-sdk')
const S3 = new AWS.S3({
    accessKeyId: ...,
    secretAccessKey: ...
})

router.post('/media', multer().single('media'), (req, res) => {
  // req.file represents the uploaded file
  let time = new Date().getTime()
  
  Promise.all([
    // original file
    S3.upload({
      Bucket: ...,
      Key: time + '_' + req.file.originalname,
      Body: req.file.buffer
    }),
    
    // large preview
    sharp(req.file)
      .resize(1200, 900)
      .toBuffer()
      .then(resized => S3.upload({
        Bucket: ...,
        Key: time + '_large_' + req.file.originalname,
        Body: resized
      }).promise()),
    
    // small thumbnail
    sharp(req.file)
      .resize(400, 300)
      .toBuffer()
      .then(resized => S3.upload({
        Bucket: ...,
        Key: time + '_small_' + req.file.originalname,
        Body: resized
      }).promise()),
  ])
  .then(() => res.send("Images uploaded"))
  .catch(e => {
    console.warn(e) // debug this error
    res.status(500).send("Unable to upload images")
  })
})

【讨论】:

  • PS:这是一个盲码,希望没有太多错别字。
  • 嗨,你建议选项 1 还是选项 2。我尝试了选项 2,但是当我在 aws 上检查图像时,它们没有调整大小。所以我选择了选项 2,它有效,但我不明白为什么。两者的主要区别是什么?
  • @kd12345。我推荐选项 1。选项 2 为您提供更大的灵活性,但除非您需要它,否则选项 1 会提供更简洁的代码。
  • 您好,您能在这里看看我的问题吗,非常感谢您的帮助。 stackoverflow.com/questions/65479245/nodejs-multer-aws-s3
  • @kd12345,看起来有点乱。尝试按原样实现此代码(选择 1)并从那里构建。
【解决方案2】:

Multer 是一个 busboy 包装器。您可以使用 busboy 而不是 multer 来处理请求并进行您需要的所有操作。

const Busboy = require('busboy');

router.post('/media', function(req, res) {

    var busboy = new Busboy({ headers: req.headers });

    busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {

      console.log('File ' + filename + ' upload incoming');

      
      file.on('end', function() {
         console.log('File ' + filename + ' upload finished');

         // make all you want, eg:
         let thumbnail = myFunctionToReturnImageFile(file);
         upload(thumbnail);

         res.send('file uploaded');
      });
    });
});

【讨论】:

  • 我知道这个答案是“没有中间件功能”的信,但我认为没有任何合理的必要不使用 multer(或类似的 mw)来解析 req.files 并使用它们在以后的功能中......
  • 嗨,我有一个非常相似的问题,请你看看。 stackoverflow.com/questions/65479245/nodejs-multer-aws-s3
【解决方案3】:

您可以尝试使用像sharp 这样的Node.js 图像处理来调整大小然后上传到S3。

sharp(req.file)
  .resize(320, 240)
  .toBuffer()
  .then(thumbnail => { upload(thumbnail) })
  .catch( err => { ... });

【讨论】:

  • 这里的问题是我无法像您使用的那样访问上传方法。它只提供用作中间件。
  • @muhammad-zeeshan 我认为您应该编写一个中间件包装调整大小和上传功能。
猜你喜欢
  • 2020-12-27
  • 2019-10-26
  • 2017-05-22
  • 1970-01-01
  • 2018-02-14
  • 1970-01-01
  • 2018-12-27
  • 2017-03-22
  • 2018-09-24
相关资源
最近更新 更多