首页 > 解决方案 > 使用 For 循环将多个文件上传到 Google Cloud Storage

问题描述

我正在尝试将多个文件上传到 Google Cloud Storage。我正在使用 for 循环来处理我要上传的文件列表中的每个文件。

但是,问题在于 for 循环不会暂停以等待上传完成,然后再继续进行下一次上传。它最终会上传它们,但是,for 循环更早完成,然后将 empty 发送回客户端urlList

如何让它暂停并等待每个上传过程,然后再转到 for 循环中的下一个文件?

const processFile = require('../middleware');
const { format } = require('util');
let uuidv4 = require('uuid/v4');

const Cloud = require('@google-cloud/storage');

const { Storage } = Cloud;
const storage = new Storage({
  keyFilename: './xxx.json',
  projectId: 'xxx'
});

const bucket = storage.bucket('xxx');

exports.upload = async (req, res) => {
  const urlList = [];
  await processFile(req, res); //multer

  for (var i = 0; i < req.files.length; i++) {

    if (!req.files[i]) {
      return res.status(400).send({ message: 'Please upload a file!' });
    }

    const { originalname, buffer } = req.files[i];
    var filename = originalname
      .toLowerCase()
      .split(' ')
      .join('-');

    filename = uuidv4() + '-' + filename;

    console.log(filename);

    const blob = bucket.file(filename);

    const blobStream = blob.createWriteStream({
      resumable: false
    });

    blobStream.on('error', err => {
      res.status(500).send({ message: err.message });
    });

    blobStream.on('finish', async data => {
      const publicUrl = format(
        `https://storage.googleapis.com/${bucket.name}/${blob.name}`
      );
      urlList.push(publicUrl);

      try {
        await bucket.file(filename).makePublic();
      } catch (err) {
        console.log('failed to make it public');
        reject(err);
      }
    });

    blobStream.end(buffer);
  }

  return res.status(200).send({
    message: 'Uploaded the files successfully',
    url: urlList
  });
};

标签: javascriptnode.jsfor-loopfile-uploadgoogle-cloud-storage

解决方案


只需将您的“上传”代码放入循环Promise中即可await。否则通过使用on其中的代码将不会遵循 for 循环。通过使用这种基于事件的代码,您的 for 循环只会通过它并且不能等待它完成。这应该可以解决问题:

const uploadFile = (f) => {
  return new Promise((resolve, reject) => {
    const { originalname, buffer } = f;
    var filename = originalname.toLowerCase().split(" ").join("-");

    filename = uuidv4() + "-" + filename;

    console.log(filename);

    const blob = bucket.file(filename);

    const blobStream = blob.createWriteStream({
      resumable: false,
    });

    blobStream.on("error", (err) => {
      res.status(500).send({ message: err.message });
      reject(err);
    });

    blobStream.on("finish", async (data) => {
      const publicUrl = format(
        `https://storage.googleapis.com/${bucket.name}/${blob.name}`
      );

      try {
        await bucket.file(filename).makePublic();
        resolve(publicUrl);
      } catch (err) {
        console.log("failed to make it public");
        reject(err);
      }
    });

    blobStream.end(buffer);
  });
};

exports.upload = async (req, res) => {
  const urlList = [];
  await processFile(req, res); //multer

  for (var i = 0; i < req.files.length; i++) {
    if (!req.files[i]) {
      return res.status(400).send({ message: "Please upload a file!" });
    }

    const publicUrl = await uploadFile(req.files[i]);
    urlList.push(publicUrl);
  }

  return res.status(200).send({
    message: "Uploaded the files successfully",
    url: urlList,
  });
};



推荐阅读