2

我正在开发一个公司 CRUD 应用程序,其中一个功能是将订阅的用户个人资料图片存储到 Google Cloud,并在需要显示时下载它。

事实是,当我需要下载它时,请求来自客户端前端,调用和特定的 GET 路由 - 例如,'/getPic'

然后我的 Node 后端服务器处理这个请求,与 Google Cloud 通信并下载文件,或多或少(简化)如下:

let localFile = fs.createWriteStream('temp/writeStreamFile.jpeg');

return new Promise((resolve,reject) =>{

   storage.bucket().file(`users/user123456/profilePicture.jpeg`)
       .createReadStream() 
       .on('end', () => {
           console.log("ended");
           resolve();
       })
       .on('response', ans => {
           console.log("responded");
       })
       .on('error', err => {
           console.error("Error", err);
           reject();
       })
       .pipe(localFile);
})

之后,我在HTTP请求的响应中返回了这张图片,就可以了。此操作的缺点是下载的文件仍存储在我的网络服务器中的文件夹('temp/writeStreamFile.jpeg')中,占用了我的服务器存储空间。

有没有办法直接在 HTTP 请求的响应中“管道”文件而不在本地保存它?

4

2 回答 2

1

您实际上可以通过管道将 ReadableStream 直接传递给您的响应。使用 express 的简单实现如下所示:

app.get('/getPic', (req, res) => {
    res.setHeader("content-type", "image/jpeg");
    storage.bucket().file(`users/user123456/profilePicture.jpeg`)
       .createReadStream() 
       .on('end', () => {
           console.log("ended");
       })
       .on('response', ans => {
           console.log("responded");
       })
       .on('error', err => {
           console.error("Error", err);
       })
       .pipe(res);
})
于 2022-01-07T02:04:36.367 回答
1

如果您不想在服务器中存储图像的临时副本,您可以生成并发送给您的用户 GCS签名 URL。这些 URL 允许在有限时间内访问存储桶文件,然后过期。由于看起来您正在使用 GCS 的 Node 客户端,因此有一种生成这些 URL 的简单方法,如文档中所示。

这是文档中的一个片段:

const {Storage} = require('@google-cloud/storage');
const storage = new Storage();
const myBucket = storage.bucket('my-bucket');

const file = myBucket.file('my-file');

//-
// Generate a URL that allows temporary access to download your file.
//-
const request = require('request');

const config = {
  action: 'read',
  expires: '03-17-2025',
};

file.getSignedUrl(config, function(err, url) {
  if (err) {
    console.error(err);
    return;
  }

  // The file is now available to read from this URL.
  request(url, function(err, resp) {
    // resp.statusCode = 200
  });
});

使用此方法,用户客户端可以直接下载图像,文档参考中有其他示例可让您调整选项,例如要使用的 URL 的可用时间。

于 2022-01-06T22:43:18.493 回答