【问题标题】:Generate multiple signed URLs from array of filenames?从文件名数组生成多个签名 URL?
【发布时间】:2021-11-22 19:38:31
【问题描述】:

我有一个使用.getFiles() 从安全 GCS 存储桶列出文件的 Node / Express 后端。然后,我遍历文件名数组并为每个文件名生成签名 URL,然后使用 probe-image-size 获取尺寸,最后将结果推送到 fileList 数组中。

这非常慢,我不得不想象我正在解决这个问题。

一个一个生成签名的 URL 似乎是最慢的部分。


let fileList = [];

listFiles().catch(console.error);

async function listFiles() {
  const [files] = await storage.bucket(bucketName).getFiles();
  for (const file of files) {
    let fileName = file.id;
    let fullPath = await generateV4ReadSignedUrl(fileName); // it takes around 500ms per filename
    let result = await probe(fullPath[0]).catch(console.error);
    fileList.push(result);
  }
  console.log('fileList=', fileList);
  return fileList;
}

async function generateV4ReadSignedUrl(fileName) {
  console.log('generate signed url');
  // temp read access
  const options = {
    version: 'v4',
    action: 'read',
    expires: Date.now() + 15 * 60 * 1000,
  };

  // v4 signed read URL
  const [url] = await storage
    .bucket(bucketName)
    .file(fileName)
    .getSignedUrl(options);
  return [url];
}

最终目标是使用自调用函数立即获取此列表,然后让它等待 React 通过以下方式调用它:

app.get('/api/photos', async (req, res) => {
  try {
    res.json({ fileList });
  } catch (err) {
    console.log('err', err);
  }
});

【问题讨论】:

  • 有了node,可以很方便的进行并发处理。异步调用所有generateV4ReadSignedUrl 方法,并在最后等待。使用这种并发性,您可以大大缩短处理时间。遗憾的是,我不是 NodeJS 开发人员,我无法指导您实现该实现。

标签: node.js express google-cloud-platform google-cloud-storage


【解决方案1】:

这是我的解决方案(加上一些额外的代码来使用 probeImageSize 包获取图像元数据。


// get remote file names
listFiles();

async function listFiles() {
  console.log('list files');
  const signedUrlArr = [];
  // concurrently get GCS files
  const [fileNameArr] = await storage.bucket(bucketName).getFiles();
  // loop through fileNameArr and concurrently generate signed URLs
  for (const file of fileNameArr) {
    signedUrlArr.push(generateV4ReadSignedUrl(file.id));
  }
  Promise.all(signedUrlArr)
    .then((signedUrlArr) => {
      // concurrently get image meta using signedURLs
      getImageMeta(signedUrlArr);
    })
    .catch((err) => {
      console.log(err);
    });
}

// concurrently generate signed URLs for each filename
function generateV4ReadSignedUrl(fileName) {
  return new Promise(async (resolve) => {
    const options = {
      version: 'v4',
      action: 'read',
      expires: Date.now() + 15 * 60 * 1000,
    };
    const [url] = await storage
      .bucket(bucketName)
      .file(fileName)
      .getSignedUrl(options);
    resolve([url][0]);
  }).catch((err) => {
    console.log(err);
  });
}

// (project specific) concurrently get image meta using probeImageSize module
function getImageMeta(signedUrlArr) {
  const probeResults = [];
  for (const url of signedUrlArr) {
    probeResults.push(probeImageSize(url));
  }
  // (project specific) take probeImage meta and create json file for `react-photo-gallery` (this can probably be done a better way that writing a json file)
  Promise.all(probeResults)
    .then((signedMeta) => {
      const galleryArr = [];
      signedMeta.forEach((metaObj) => {
        galleryArr.push({
          src: metaObj.url,
          width: metaObj.width,
          height: metaObj.height,
        });
      });
      console.log('galleryArr', galleryArr);
      fs.writeFileSync(
        '../frontend/src/helpers/photos.json',
        JSON.stringify(galleryArr),
      );
    })
    .catch((err) => {
      console.log(err);
    });
}

// concurrently get image meta data
function probeImageSize(signedUrl) {
  return new Promise(async (resolve) => {
    const meta = await probe(signedUrl).catch(console.error);
    resolve(meta);
  }).catch((err) => {
    console.log(err);
  });
}

【讨论】:

    猜你喜欢
    • 2020-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-11
    • 1970-01-01
    • 2020-09-06
    • 2012-05-22
    相关资源
    最近更新 更多