99 lines
3.3 KiB
JavaScript
99 lines
3.3 KiB
JavaScript
const fs = require('fs');
|
||
const path = require('path');
|
||
const { execFile } = require('child_process');
|
||
const { v4: uuidv4 } = require('uuid');
|
||
const express = require('express'); // JSON解析用にexpressをインポート
|
||
const { API_KEY } = require('../config.js'); // API_KEYをインポート
|
||
|
||
// tmpディレクトリのパス
|
||
const tmpDir = path.join(__dirname, 'tmp');
|
||
|
||
// tmpディレクトリが存在しない場合は作成
|
||
if (!fs.existsSync(tmpDir)) {
|
||
fs.mkdirSync(tmpDir);
|
||
}
|
||
|
||
// POSTエンドポイント
|
||
module.exports = (app) => {
|
||
app.post('/pdfToText', express.json({ limit: '30mb' }), async (req, res) => {
|
||
try {
|
||
// APIキーのチェック
|
||
const apiKey = req.headers['x-api-key'];
|
||
if (!apiKey || apiKey !== API_KEY) {
|
||
console.log('APIキーが不正です');
|
||
return res.status(401).json({ error: 'APIキーが不正です' });
|
||
}
|
||
|
||
// base64, fileName の3つをチェック
|
||
const { base64, fileName } = req.body;
|
||
if (!base64 || !fileName) {
|
||
return res.status(400).json({ error: 'base64とfileNameは必須です' });
|
||
}
|
||
|
||
const txtBuffer = await pdfToTextConvert(base64, fileName);
|
||
const safeFileName = encodeURIComponent(path.parse(fileName).name); // ファイル名をエスケープ
|
||
res.set({
|
||
'Content-Type': 'text/plain',
|
||
'Content-Disposition': `attachment; filename="${safeFileName}.txt"`
|
||
});
|
||
res.send(txtBuffer);
|
||
} catch (err) {
|
||
console.error('変換エラー:', err.message);
|
||
res.status(500).json({ error: err.message });
|
||
}
|
||
});
|
||
};
|
||
|
||
// PDF テキスト変換処理
|
||
async function pdfToTextConvert(base64) {
|
||
const tempId = uuidv4(); // 一意のIDを生成
|
||
const pdfPath = path.join(tmpDir, `${tempId}.pdf`);
|
||
const outputPath = path.join(tmpDir, `${tempId}.txt`);
|
||
|
||
// base64データをファイルに保存
|
||
fs.writeFileSync(pdfPath, Buffer.from(base64, 'base64'));
|
||
|
||
// pdfuniteでテキストに変換
|
||
await new Promise((resolve, reject) => {
|
||
const child = execFile(
|
||
'pdftotext',
|
||
[
|
||
'-layout',
|
||
'-nopgbrk',
|
||
pdfPath,
|
||
outputPath
|
||
],
|
||
(error, stdout, stderr) => {
|
||
if (error) {
|
||
console.error('stderr:', stderr);
|
||
reject(error);
|
||
} else {
|
||
resolve();
|
||
}
|
||
}
|
||
);
|
||
// 60秒タイムアウト
|
||
const timeout = setTimeout(() => {
|
||
child.kill('SIGTERM'); // SIGTERMを使用してプロセスを終了
|
||
reject(new Error('テキストへの変換がタイムアウトしました(60秒経過)'));
|
||
}, 60000);
|
||
child.on('exit', () => clearTimeout(timeout));
|
||
});
|
||
|
||
// 変換されたテキストファイルを読み込み
|
||
if (!fs.existsSync(outputPath)) {
|
||
// cleanup
|
||
fs.unlinkSync(pdfPath);;
|
||
throw new Error('テキストへの変換に失敗しました');
|
||
}
|
||
const txtBuffer = fs.readFileSync(outputPath);
|
||
|
||
// cleanup
|
||
fs.unlinkSync(pdfPath);
|
||
fs.unlinkSync(outputPath);
|
||
|
||
return txtBuffer;
|
||
}
|
||
|
||
|