使用For循环将多个图像上传到Google Cloud Storage

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

我有一个包含 220k 个产品的数据库,每个产品都有 1-3 个图像链接(全部小于 200kb)。我需要检查所有这些并将它们直接上传到 Google Cloud Storage,而无需在本地下载。这是我想出的方法:

const saveFileFromUrl = (sneakerData: any, size: string, index: number) => {
  const imageURL: string = resolveObject(`image_${size}`, sneakerData) 
  if(!imageURL.includes("https://")) return("not a link")
  const req = request(imageURL)
  req.on('response', res => {
    if(res.statusCode !== 200) return
    const imageType = res.headers['content-type']?.split('/')[1]
    const writeStream = storage.bucket(bucketName).file(`${sneakerData.sneaker_id}/${size}.${imageType}`).createWriteStream({
      gzip: true,
      metadata: {
        contentType: res.headers['content-type']
      }
    })
    req.pipe(writeStream)
    .on('finish', () => console.log(`SUCCESS INDEX: ${index}`))
    .on('error', ()=> {
      writeStream.end();
      console.log('ERROR INDEX: ' + index)
    })

    req.resume();
  })
  req.on('error', err => console.log(err))
}
const app = async() => {
    const data = await getLinks();
    console.log("STARTING")
    for(let i in data){ 
      for(let j in imageSizes){
        await saveFileFromUrl(data[Number(i)],imageSizes[Number(j)], Number(i))
      }
    }
}

此脚本适用于前 ~1k 图像,但随后我再次遇到相同的错误:

Error: connect ETIMEDOUT
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1278:16) {
  errno: -4039,
  code: 'ETIMEDOUT',
  syscall: 'connect',
  address: '',
  port: 443
}

我还尝试了 Promise 方法,将 Promise 推送到数组,然后最后使用 Promise.all,但结果是相同的。

我对 Google Cloud Platform 相当陌生,因此任何提示、技巧或解决方法都会对我有很大帮助,谢谢。

node.js express google-cloud-platform google-cloud-storage
1个回答
0
投票

您正在尝试这样做:

await saveFileFromUrl(...)

但是,

saveFileFromUrl()
不会返回承诺,因此
await
没有做任何有用的事情。这会导致您的所有上传并行运行,这显然会占用一些资源。

您可以更改

saveFileFromUrl()
以返回一个在操作完成时解析/拒绝的承诺(您必须修复一些 TypeScript 语法):

const saveFileFromUrl = (sneakerData: any, size: string, index: number) => {
    return new Promise((resolve, reject) => {
        const imageURL: string = resolveObject(`image_${size}`, sneakerData)
        if (!imageURL.includes("https://")) {
            reject("not a link");
            return;
        }   
        const req = request(imageURL);
        req.on('response', res => {
            if (res.statusCode !== 200) return
            const imageType = res.headers['content-type']?.split('/')[1]
            const writeStream = storage.bucket(bucketName).file(`${sneakerData.sneaker_id}/${size}.${imageType}`).createWriteStream({
                gzip: true,
                metadata: {
                    contentType: res.headers['content-type']
                }
            })
            req.pipe(writeStream).on('finish', () => {
                console.log(`SUCCESS INDEX: ${index}`)
                resolve();
            }).on('error', e => {
                writeStream.end();
                console.log('ERROR INDEX: ' + index)
                reject(e);
            });
        })
        req.on('error', err => {
            console.log(err)
            reject(err);
        });
    });
}
© www.soinside.com 2019 - 2024. All rights reserved.