首页 > 解决方案 > 如何创建 WriteStream() 到 GCS?

问题描述

我正在尝试编写一个 Express 路由,该路由在 POST 正文中获取图像 URI,然后将图像保存到 Google Cloud Storage Bucket 中。

我无法将此图像保存到本地磁盘,需要将缓冲区直接流式传输到 GCS 存储桶。

我的路线在 GCS 存储桶中创建了一个 4KB 的“存根”,但没有图像有效负载。然后我的nodejs继续崩溃......

问:将 https.request() 的结果 .pipe() 到 blob.createWriteStream() 的正确方法是什么?这是正确的方法吗?

我花了几天时间尝试使用不同的流处理程序找到正确的解决方案,但几乎没有什么进展可以展示。有人可以帮忙吗?

message: 'The rate of change requests to the object my-projectID/testimage.jpg exceeds the rate limit. Please reduce the rate of create, update, and delete requests.'
  const streamifier = require('streamifier');
  const {Storage} = require('@google-cloud/storage');
  const storage = new Storage({
      projectId: 'my-projectID',
      keyFile: '../config/my-projectID.json'
      });
  const bucket = storage.bucket('my-projectID');
  const blob = bucket.file('testimg.jpg');

app.post('/bam', passport.authenticate('basic', {session: false }), (req, res) => {
    
return new Promise((resolve, reject) => {
        https.request(req.body.pic, (response) => {            
            response.on('data', (d) => {
                streamifier.createReadStream(d)
                .pipe(blob.createWriteStream({
                    resumable:false, 
                    public:true,
                    metadata:{ contentType: 'image/jpeg' }
                    }));
            });
            
            response.on('finish', (done) => {
                console.log(done);
            });

            response.on('error', (err) => {
                console.log(err);
            });

        }).end();
    }); 

});

** 为我丑陋的 JS 道歉,我仍然处于 ES6 学习曲线的底部。

标签: node.jsexpressgoogle-cloud-storage

解决方案


如果您的目标是将图像保存到 GCS,则必须创建一个 Promise 然后解析它。根据谷歌云存储文档,你必须实例化一个新的存储对象,然后指向你想要的存储桶,然后创建一个通过“createWriteStream”将文件上传到存储桶的承诺,然后解决你想要的承诺。IE 在这里我将文件上传到存储桶,然后返回公共 url。如果您看一下这段代码,这是为 GCS 创建 WriteStream 的正确方法。它比你的更复杂和不同的功能只是因为在这里你可以使用 foreach 循环上传多个文件,但创建到 GCS 的流的过程基本上保持不变。这是我在控制器中的功能:

控制器/postControllers.js:

const {Storage} = require('@google-cloud/storage');
const storage = new Storage();
const bucket = storage.bucket(process.env.GCLOUD_STORAGE_BUCKET);

//Func to upload files to GCS
const uploadFileTGcs = async (file) => {
  let promises = [];
  _.forEach(file, (value, key) => {
    const {originalname, buffer} = value;
    const blob = bucket.file(originalname.replace(/ /g, '_'));

    const promise = new Promise((resolve, reject) => {
      const blobStream = blob.createWriteStream({
        resumable: false,
        public: true,
      });
      blobStream.on('error', () => {
        reject(`Unable to upload image, something went wrong`);
      }).on('finish', async () => {
        const publicUrl = format(
            `https://storage.googleapis.com/${bucket.name}/${blob.name}`,
        );
        resolve(publicUrl);
      }).end(buffer);
    });
    promises.push(promise);
  });
  return Promise.all(promises).then(promises => {
    return promises;
  });
};

然后在路线中,我可以将该功能用作中间件:

router.post('/create', async (req, res, next) => {
  try {
    if (!req.files) {
      res.status(400).json({
        messages: 'No file uploaded',
      });
      return;
    }

    const promiseReturned = await postsController.uploadFileTGcs(req.files);

    ....

    res.status(promiseReturned ? 200 : 404).json({
      result: promiseReturned, //here I'm returning the url of the files stored in gcs
      message: 'Post created',
    });
  } catch (e) {
    res.status(500).json({
      result: e.toString(),
    });
  }
});

推荐阅读