【问题标题】:How to chain writeFile() and OCR with NodeJS in Google Cloud Functions?如何在 Google Cloud Functions 中使用 NodeJS 链接 writeFile() 和 OCR?
【发布时间】:2019-12-07 15:13:56
【问题描述】:

场景如下:

从 Amazon S3 存储桶中提取文件,然后将其存储在临时文件夹中,然后使用 API 执行对象字符识别。 不幸的是,这不起作用,我认为这是由于异步/同步执行,但我已经尝试了几种带有回调/承诺的变体,但没有进一步了解。 如果有人能给我关于如何构建这个场景的提示,我将不胜感激!

当前的错误是:

TypeError: Cannot read property 'writeFile' of undefined at Response.<anonymous> (/srv/index.js:38:32) (it's the 'await fs.writeFile(dir,data);' line)


/**
 * Responds to any HTTP request.
 *
 * @param {!express:Request} req HTTP request context.
 * @param {!express:Response} res HTTP response context.
 */
const AWS = require('aws-sdk');
const fs = require('fs').promises;
const Vision = require('@google-cloud/vision');
var os = require('os');

exports.helloWorld = async (req,res) => {

    var bucket, fileName, fileUrl;
    req.on('data', chunk => {
        body += chunk.toString();
        data.push(chunk);
    });
    req.on('end', () => {
        bucket = JSON.parse(data).value1;
        fileName = JSON.parse(data).value2;
        fileUrl = JSON.parse(data).value3;

        var s3 = new AWS.S3();

        s3.getObject({
                Bucket: bucket,
                Key: fileName
            },
            async function(error, data) {
                if (error != null) {
                    console.log("Failed to retrieve an object: " + error);
                } else {
                    console.log("Loaded " + data.ContentType + " bytes");
                    var tmpdir = os.tmpdir();
                    var dir = tmpdir+'/'+fileName;
                    try{
                      await fs.writeFile(dir,data);
                      const vision = new Vision.ImageAnnotatorClient();
                      let text;
                      await vision
                          .textDetection('/tmp/' + fileName)
                          .then(([detections]) => {
                              const annotation = detections.textAnnotations[0];
                              console.log(1);
                              text = annotation ? annotation.description : '';
                              console.log(`Extracted text from image (${text.length} chars)`);
                              console.log(1);
                              console.log(text);
                              resolve("Finished ocr successfully");
                          })
                          .catch(error =>{
                            console.log(error);
                            reject("Error with OCR");
                          })
                    }catch(error){
                      console.log(error);
                    }
                }
            },
        );

        let message = bucket + fileName + fileUrl;
        res.status(200).send(message);
    });
};

【问题讨论】:

    标签: node.js google-cloud-platform google-cloud-functions


    【解决方案1】:

    您会收到该错误,因为您在旧版本的 Node (&lt; 10.0.0) 上运行,其中 fs.promises 不可用。这就是为什么 fs 是未定义的,你会得到:

    TypeError: Cannot read property 'writeFile' of undefined at Response.<anonymous> (/srv/index.js:38:32) (it's the 'await fs.writeFile(dir,data);' line)
    

    要么使用更新的版本,要么只承诺代码。

    const { promisify } = require('util');
    const fs = require('fs');
    // const fs = require('fs').promises
    
    const writeFile = promisify(fs.writeFile);
    

    现在在您的代码中使用writeFile 而不是fs.writeFile


    除此之外,您的代码还有一些问题。

     req.on('data', chunk => {
            body += chunk.toString();
            data.push(chunk);
        });
    

    data 没有在任何地方定义,鉴于接下来的几行,将数据推送到数组中然后在该数组上运行 JSON.parse 是没有意义的。

    bucket = JSON.parse(data).value1;
    fileName = JSON.parse(data).value2;
    fileUrl = JSON.parse(data).value3;
    

    此外,JSON.parse 应该只调用一次,而不是解析相同的字符串(代码中的数组,会产生错误)3 次。

    const values = JSON.parse(body); // should be body instead of data with the posted code
    bucket = values.value1;
    fileName = values.value2;
    fileUrl = values.value3;
    

    只需在JSON 中发布bucketfileNamefileUrl 而不是valueN,就可以大大改善这一点。

    const { bucket, fileName, fileUrl } = JSON.parse(body);
    

    整个代码可以改写成:

    const AWS = require('aws-sdk');
    const { promisify } = require('util');
    const fs = require('fs');
    const Vision = require('@google-cloud/vision');
    const os = require('os');
    const path = require('path');
    
    const writeFile = promisify(fs.writeFile);
    
    
    exports.helloWorld = async (req,res) => {
    
        let body = '';
        req.on('data', chunk => {
            body += chunk.toString();        
        });
    
        req.on('end', async() => {
            // post { "bucket": "x", "fileName": "x", "fileUrl": "x" }
            const { bucket, fileName, fileUrl } = JSON.parse(body);
    
            var s3 = new AWS.S3();
    
            try {
    
              const data = await s3.getObject({
                Bucket: bucket,
                Key: fileName
              }).promise();
    
              const tmpdir = os.tmpdir();
              const filePath = path.join(tmpdir, fileName)
    
              await writeFile(filePath, data);
    
              const vision = new Vision.ImageAnnotatorClient();          
              const [detections] = await vision.textDetection(filePath)
              const annotation = detections.textAnnotations[0];
              const text = annotation ? annotation.description : '';
              console.log(`Extracted text from image (${text.length} chars)`);
    
    
              let message = bucket + fileName + fileUrl;
              res.status(200).send(message);
    
            } catch(e) {
              console.error(e);
              res.status(500).send(e.message);
            }
        });
    };
    

    注意:我不知道Vision API 是否像这样工作,但我使用的逻辑和参数与您使用的相同。

    【讨论】:

    • 感谢您的帮助,我不知道 promisify
    猜你喜欢
    • 2019-07-11
    • 2017-08-18
    • 2021-12-26
    • 2020-09-19
    • 1970-01-01
    • 2017-10-03
    • 2017-10-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多