[OCR] Node Express Server Example
Sample Node/Express endpoint that proxies OCR requests.
const express = require('express');
const bodyParser = require('body-parser');
const request = require('request');
const fs = require('fs');
const path = require('path');
const multer = require('multer');
const ROOT_DIR = path.resolve(__dirname, '..'); // project root
const FILE_UPLOAD_DIR = path.resolve(ROOT_DIR, 'tmp/files'); // upload destination
const OCR_RESULT_DIR = path.resolve(ROOT_DIR, 'tmp/work'); // processed image destination
const OCR_API_URL = ''; // OCR API URL
const OCR_API_KEY = ''; // OCR API key
const OCR_OPTIONS = {
// 'type' is set per-request below (depends on whether fid is provided — 3.0.2403, 2.18.2403+)
coord: 'origin',
skew: 'image',
boxes_type: 'all',
save_mask: 'true',
textout: 'true',
recog_form: 'true',
extract_table: 'true'
};
const app = express();
const router = express.Router();
const uploader = multer({ dest: FILE_UPLOAD_DIR });
router.post('/request', uploader.single('file'), async (req, res) => {
const file = req.file;
const page = (req.body || {}).page || 0;
const fid = req.body.fid;
let filePathWithExt;
if (!fid) { // 3.0.2403, 2.18.2403+
const originalName = file.originalname;
const mimeType = file.mimetype;
const extension = path.extname(originalName).split('.')[1] || mimeType.split('/')[1];
filePathWithExt = file.path + '.' + extension;
fs.renameSync(file.path, filePathWithExt);
}
try {
const ocrResult = await requestOCR(filePathWithExt, page, fid);
const imagePath = await downloadImage(ocrResult.result.masked_image);
res.end(JSON.stringify({ result: ocrResult.result, imagePath }));
} catch (error) {
res.status(error.status).send(error.message);
}
});
function requestOCR(imgPath, page, fid) {
return new Promise((resolve, reject) => {
const typeOption = {};
if (!fid) { // 3.0.2403, 2.18.2403+
typeOption.type = 'upload';
typeOption.image = fs.createReadStream(imgPath);
} else {
typeOption.type = 'page';
typeOption.fid = fid;
}
const options = {
url: `${OCR_API_URL}/ocr`,
formData: {
api_key: OCR_API_KEY,
page_index: page,
...typeOption,
...OCR_OPTIONS
}
};
request.post(options).on('response', response => {
if (response.statusCode === 200) {
let chunks = [];
response
.on('error', err => { throw err; })
.on('data', chunk => chunks.push(chunk))
.on('end', () => resolve(JSON.parse(Buffer.concat(chunks).toString())));
} else {
const err = new Error(response.statusMessage);
err.status = response.statusCode;
reject(err);
}
});
});
}
function downloadImage(fileName) {
return new Promise((resolve, reject) => {
const options = {
url: `${OCR_API_URL}/out/${fileName}`,
formData: { api_key: OCR_API_KEY }
};
const imagePath = path.resolve(OCR_RESULT_DIR, fileName);
request.post(options).on('response', response => {
if (response.statusCode === 200) {
let imageData = Buffer.from([]);
response
.on('data', chunk => { imageData = Buffer.concat([imageData, chunk]); })
.on('end', () => {
fs.writeFileSync(imagePath, imageData);
const relativeImagePath = '/' + path.relative(ROOT_DIR, imagePath).replace(/\\/g, '/');
resolve(relativeImagePath);
});
} else {
const err = new Error(response.statusMessage);
err.status = response.statusCode;
reject(err);
}
});
});
}
app.use(bodyParser.json());
app.use('/', router);
app.listen(8080);