node.js - 如何在 Google Cloud Functions 中使用 NodeJS 链接 writeFile() 和 OCR?
问题描述
场景如下:
从 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 ( < 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;
这可以通过发布来大大改善bucket
,而不是fileName
。fileUrl
JSON
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 是否像这样工作,但我使用了您正在使用的相同逻辑和参数。
推荐阅读
- php - Nginx + Php-fpm fastcgi 上游超时
- node.js - React 应用程序无法加载 localhost:3000
- visual-studio - 无法从 VS2017 加载模板到 VS2019
- python - Python Scrapy Crawler - 尝试在 Github 上自动记录问题不起作用 - Gist 无法在 Linux 机器上创建(适用于 Windows)
- qt - 将 CMake 项目导入现有 QT 项目 .pro
- postgresql - Spring Batch - 多步执行模型,如果第 3 步失败,则第 1 步和第 2 步插入的数据也应该回滚
- apache-flink - Apache Flink 中的不可序列化对象
- java - Apache POI 获取字体指标
- javascript - 来自 puppeteer 文档的代码在 UnhandledPromiseRejectionWarning 之前不起作用
- java - 如何测试副屏?