首页 > 解决方案 > 使用 multer 将多个文件发送到谷歌存储桶 - 为什么我的文件是空的?

问题描述

我之前设置了一个文件上传并正常工作。现在我需要让它处理多个文件。

这是我现在的代码:

const multer = require('multer')
const { Storage } = require('@google-cloud/storage')

const storage = new Storage()

const m = multer({ storage: multer.memoryStorage()  })

module.exports = app => {
  app.use('/', router)
  router.post(
    '/reader-:shortId/file-upload',
    passport.authenticate('jwt', { session: false }),
    m.array('files'),
    async function (req, res) {
      const bucketName = req.params.shortId.toLowerCase()
      await storage.createBucket(bucketName)
      bucket = storage.bucket(bucketName)
      let promises = []

      req.files.forEach((file) => {
        const blob = bucket.file(file.originalname)
        const newPromise =  new Promise((resolve, reject) => {
          blob.createWriteStream({
            metadata: { contentType: file.mimetype }
          }).on('finish', async response => {
            await blob.makePublic()
            resolve(response)
          }).on('error', err => {
            reject('upload error: ', err)
          }).end()
        })
       promises.push(newPromise)
     })

     Promise.all(promises).then((response) => {
       // the response I get here is [undefined, undefined]
       res.status(200).send(response)
     }).catch((err) => {
       res.status(400).send(err.message)
     });
    })
  }

req.files 确实给了我一个文件数组,带有一个缓冲区和一个有意义的大小。承诺全部解决。但是一旦我检查了谷歌存储桶中的文件,它们的名称是正确的,但没有任何内容(大小为 0)

正如我之前所说,当我使用一个文件(使用 m.single('file')

我不想将存储桶用作 multer 设置的目的地,因为在上传到谷歌存储桶之前我还必须更改文件名。

编辑:这是谷歌云文档为单个文件上传提供的代码示例(https://cloud.google.com/nodejs/getting-started/using-cloud-storage):

function sendUploadToGCS (req, res, next) {
  if (!req.file) {
    return next();
  }

  const gcsname = Date.now() + req.file.originalname;
  const file = bucket.file(gcsname);

  const stream = file.createWriteStream({
    metadata: {
      contentType: req.file.mimetype
    },
    resumable: false
  });

  stream.on('error', (err) => {
    req.file.cloudStorageError = err;
    next(err);
  });

  stream.on('finish', () => {
    req.file.cloudStorageObject = gcsname;
    file.makePublic().then(() => {
      req.file.cloudStoragePublicUrl = getPublicUrl(gcsname);
      next();
    });
  });

  stream.end(req.file.buffer);
}

我最初有类似的工作,但我只是不明白它从哪里获取文件缓冲区数据。这可能是多个文件的不同之处。

标签: javascriptnode.jsgoogle-cloud-storagemulter

解决方案


我知道为时已晚,但有人可能会寻找在 Google Cloud Storage 上上传多个文件的答案。

依赖项:

  • 表达
  • 谷歌云库
  • 穆尔特
  • 身体解析器

这是控制器代码。

exports.post_image_upload = async (req, res) => {
   /** Check if file exist */
   if (!req.files) {
       res.status(400).send('No file uploaded.');
       return;
   }

   let PublicUrls = []

   req.files.forEach((file) => {
       const blob = bucket.file(file.fieldname + '-' + Date.now() + path.extname(file.originalname))

       const blobStream = blob.createWriteStream({
           metadata: { contentType: file.mimetype }
       })
       blobStream.on('finish', ()=> {
           blob.makePublic()           
       })
       blobStream.on('error', err => {
           //Put your error message here
       })
       blobStream.end(file.buffer)

       const Url = `https://storage.googleapis.com/${bucket.name}/${blob.name}`

       PublicUrls.push(Url)
   })

   res.send(PublicUrls)
}

祝你好运


推荐阅读