SSE streaming added unnecessary complexity and latency due to buffering issues across Node.js event loop, Nginx proxy, and Docker layers. Reverted to a simple synchronous request/response for PDF conversion. Kept extractLlmErrorMessage for user-friendly LLM errors, lazy-loaded pdf-parse, and extended Nginx timeout.
91 lines
2.2 KiB
TypeScript
91 lines
2.2 KiB
TypeScript
import { Router } from 'express';
|
|
import multer from 'multer';
|
|
import { asyncHandler } from '../utils';
|
|
import { importStatement, isValidationError } from '../services/import';
|
|
import {
|
|
convertPdfToStatement,
|
|
isPdfConversionError,
|
|
} from '../services/pdfToStatement';
|
|
|
|
const upload = multer({
|
|
storage: multer.memoryStorage(),
|
|
limits: { fileSize: 15 * 1024 * 1024 },
|
|
});
|
|
|
|
function isPdfFile(file: { mimetype: string; originalname: string }): boolean {
|
|
const name = file.originalname.toLowerCase();
|
|
return (
|
|
file.mimetype === 'application/pdf' ||
|
|
name.endsWith('.pdf')
|
|
);
|
|
}
|
|
|
|
function isJsonFile(file: { mimetype: string; originalname: string }): boolean {
|
|
const name = file.originalname.toLowerCase();
|
|
return (
|
|
file.mimetype === 'application/json' ||
|
|
name.endsWith('.json')
|
|
);
|
|
}
|
|
|
|
const router = Router();
|
|
|
|
router.post(
|
|
'/statement',
|
|
upload.single('file'),
|
|
asyncHandler(async (req, res) => {
|
|
const file = req.file;
|
|
if (!file) {
|
|
res.status(400).json({
|
|
error: 'BAD_REQUEST',
|
|
message: 'Файл не загружен',
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (!isPdfFile(file) && !isJsonFile(file)) {
|
|
res.status(400).json({
|
|
error: 'BAD_REQUEST',
|
|
message: 'Допустимы только файлы PDF или JSON',
|
|
});
|
|
return;
|
|
}
|
|
|
|
let body: unknown;
|
|
|
|
if (isPdfFile(file)) {
|
|
const converted = await convertPdfToStatement(file.buffer);
|
|
if (isPdfConversionError(converted)) {
|
|
res.status(converted.status).json({
|
|
error: converted.error,
|
|
message: converted.message,
|
|
});
|
|
return;
|
|
}
|
|
body = converted;
|
|
} else {
|
|
try {
|
|
body = JSON.parse(file.buffer.toString('utf-8'));
|
|
} catch {
|
|
res.status(400).json({
|
|
error: 'BAD_REQUEST',
|
|
message: 'Некорректный JSON-файл',
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
|
|
const result = await importStatement(body);
|
|
if (isValidationError(result)) {
|
|
res.status((result as { status: number }).status).json({
|
|
error: (result as { error: string }).error,
|
|
message: (result as { message: string }).message,
|
|
});
|
|
return;
|
|
}
|
|
res.json(result);
|
|
}),
|
|
);
|
|
|
|
export default router;
|