在Node中发送多个文件到GCS

问题描述 投票:0回答:2

因此,我需要更改 Google Cloud Storage 的此功能,以便它可以上传多个文件而不是一个。我正在尝试找到一个好的解决方案,使其始终等待所有文件上传。不知道如何使其异步 - 我应该在

stream.on('finish',(...))
上等待还是在
file.makePublic().then(...)
上等待,这绝对是一个 Promiste,我可以用
Promise.all()
收集然后解决
next()

或者如果谷歌已经有一个没有在他们的文档中披露的解决方案,那就更好了。

功能:

function sendUploadsToGCS (req, res, next) {
  if (!req.files) {
    return next()
  }

  let vals = Object.values(req.files)

  for(let f of vals){
    const gcsname = Date.now() + f[0].originalname
    const file = bucket.file(gcsname)

    const stream = file.createWriteStream({
      metadata: {
        contentType: f[0].mimetype
      },
      resumable: false
    })

    stream.on('error', (err) => {
      f[0].cloudStorageError = err
      next(err)
    })

    stream.on('finish', () => {
      f[0].cloudStorageObject = gcsname;
      file.makePublic().then(() => {
        f[0].cloudStoragePublicUrl = getPublicUrl(gcsname)
        console.log('pub url: ', getPublicUrl(gcsname))
        next()
      })
    })

    stream.end(f[0].buffer)
  }
}

原始函数(针对一个文件):https://cloud.google.com/nodejs/getting-started/using-cloud-storage#upload_to_cloud_storage

node.js google-cloud-storage
2个回答
3
投票

我是这样解决的:

function sendUploadsToGCS (req, res, next) {
  if (!req.files) {
    return next()
  }

  let promises = []
  let vals = Object.values(req.files)

  for(let f of vals){
    const gcsname = Date.now() + f[0].originalname
    const file = bucket.file(gcsname)

    const stream = file.createWriteStream({
      metadata: {
        contentType: f[0].mimetype
      },
      resumable: false
    })

    stream.on('error', (err) => {
      f[0].cloudStorageError = err
      next(err)
    })

    stream.end(f[0].buffer)

    promises.push(
      new Promise ((resolve, reject) => {
        stream.on('finish', () => {
          f[0].cloudStorageObject = gcsname;
          file.makePublic().then(() => {
            f[0].cloudStoragePublicUrl = getPublicUrl(gcsname)
            resolve()
          })
        })
      })
    )
  }
  Promise.all(promises).then(() => next())
}

0
投票

我在处理大量小文件时也遇到了类似的问题。为了控制上传,我决定使用 p-limit 库,它处理并发请求限制,并且我仅在代码中的这一位置上传所有文件。

这种方法让我获得了与此类似的结果:

Number of files to upload:  186
All files uploaded to GCS:  207.94119999930263  ms

这是我为其他处理此问题的人提供的代码:

const downloadSatelliteFiles = async (files: FileData[]) => {
    const limit = pLimit(5);
    const promises: Promise<void>[] = [];

    files.forEach((file) => {
        promises.push(
            limit(() => {
                uploadFileToGCS(file.fileName, file.buffer, file.contentType);
            })
        );
    });

    await Promise.all(promises);

    return;
};

const uploadFileToGCS = (filename: string, data: any, contentType: string) => {
    return new Promise(async (resolve, reject) => {
        const file = storage.bucket(process.env.GCLOUD_STORAGE_BUCKET).file(filename);

        const stream = file.createWriteStream({
            metadata: {
                contentType,
                cacheControl: "no-cache",
            },
            resumable: false,
        });
        stream.on("error", (err) => {
            console.log("UPLOAD_ERROR");
            console.log(err);
        });
        stream.on("finish", () => {
            resolve("ok");
        });
        stream.end(data);
    });
};
© www.soinside.com 2019 - 2024. All rights reserved.