- Извлекает поля формы из PDF-файла
- Преобразует их в наложенные объекты
- Использует эти наложения для программного заполнения PDF-файлов
Мои извлеченные поля PDF содержат поля символов (несколько небольших полей для ввода фиксированной длины), но они всегда возвращаются как «type»: «textfield».
Я хочу, чтобы поля символов обрабатывались как «type»: «textbox», сохраняя при этом обычный текстовый ввод как текстовое поле.
В настоящее время любой неизвестный тип возвращается к текстовому полю.
Текущий тип Определения
Код: Выделить всё
export type OverlayType = 'textfield' | 'checkbox' | 'textarea' | 'radio';
const ALLOWED_TYPES = ["textfield", "textarea", "checkbox", "radio"] as const;
const isAllowedType = (s: string): s is OverlayType =>
(ALLOWED_TYPES as readonly string[]).includes(s);
const coerceType = (t: any): OverlayType => {
const s = typeof t === "string" ? t.toLowerCase().trim() : "";
return isAllowedType(s) ? (s as OverlayType) : "textfield";
};
Код: Выделить всё
public static async downloadPdfFromData(req: Request, res: Response) {
try {
const { pdfId,name,formData, formId } = req.body;
console.log('PDF ID:', pdfId, 'Name:', name);
if (!pdfId || !name) {
return res.status(400).json({
message: 'PDF ID and name are required.',
});
}
//Get the overlays directly from the forms collection
// Create Basic Auth header value
const authHeader = 'Basic ' + Buffer.from(`${RESTHEART_CREDENTIALS_NAME}:${RESTHEART_CREDENTIALS_PASS}`).toString('base64');
const organizationName = req.headers['x-organization-name'];
const formColl = `${organizationName}_forms`
console.log(`${API_NOSQL_URL}/${formColl}/${formId}?keys={"components":1,"_id":0}`);
const projectResponse = await axios.get(`${API_NOSQL_URL}/${formColl}/${formId}?keys={"components":1,"_id":0}`, {
headers: { 'Authorization': authHeader }
});
// Fetch the PDF from S3
const bucketName = S3_BUCKET_NAME_PDF_FORMS;
const key = `pdf-forms/${pdfId}/${name}`;
const s3Response = await s3Client.send(new GetObjectCommand({ Bucket: bucketName, Key: key }));
const s3Stream = s3Response.Body;
// const overlays: Overlay[]= JSON.parse(projectResponse.data.components) as Overlay[];
// data.components is already an array, not a JSON string
if (!Array.isArray(projectResponse.data.components)) {
throw new Error("Did not return components array");
}
const overlays: Overlay[] = projectResponse.data.components
.filter((c: any) => c && c.overlay && c.key && c.type)
.map((c: any) => ({
type: coerceType(c.type),
key: c.key,
label: c.label ?? "",
overlay: {
width: Number(c.overlay.width),
height: Number(c.overlay.height),
top: Number(c.overlay.top),
left: Number(c.overlay.left),
page: Number(c.overlay.page),
},
input: Boolean(c.input),
tableView: Boolean(c.tableView),
...(c.value !== undefined ? { value: String(c.value) } : {}),
}));
console.log('Overlays:', overlays);
//console.log('formdata:', formData);
//Get the overlays and form data from request body
let configPdfSize = {
method: 'get',
url: POSTGREST + '/pdf_forms?id=eq.'+ pdfId,
headers: {
'Content-Type': 'application/json'
}
};
const applicationDetailsPdfSize = await axios.request(configPdfSize);
if (!applicationDetailsPdfSize.data || applicationDetailsPdfSize.data.length === 0) {
return res.status(404).json({ message: 'PDF Page Size not found in database.' });
}
const pdfPageSize = applicationDetailsPdfSize.data[0].pdf_page_sizes;
if (!pdfPageSize) {
return res.status(500).json({ message: 'pdfPageSize not found in DB record.' });
}
const pdfPageSizeObj: Record = JSON.parse(pdfPageSize);
// console.log('pdfPageSizeObj',pdfPageSizeObj);
const filledPdfBuffer = await fillPdfAuto(
s3Response.Body,
overlays,
typeof formData === "string" ? JSON.parse(formData) : formData,
pdfPageSizeObj,
{
fontSize: 10,
minFontSize: 6,
textOverflow: "shrink",
padding: 2,
// For flattened PDFs (if you know html page px sizes from pdf2htmlex), pass them here:
// pagePixelSize: { 1:{w:1089.36,h:1410}, 2:{w:1089.36,h:1410}, 3:{w:1089.36,h:1410} },
pxPerPt: 96/72, // safe default for image PDFs
tinyBoxCenter: true // helps tiny boxes
}
);
//console.log('Filled PDF Buffer Length:', filledPdfBuffer.length);
//fs.writeFileSync('FilledForm-Flat.pdf', filledPdfBuffer);
// 3️⃣ Send as download
res.setHeader('Content-Type', 'application/pdf');
res.setHeader('Content-Disposition', `attachment; filename="${pdfId}-final.pdf"`);
res.send(filledPdfBuffer);
//console.log(JSON.stringify(components, null, 2));
//return res.status(200).json(components);
} catch (error: any) {
console.error('Error extracting text from PDF:', error.message);
return res.status(500).json({
message: 'An error occurred while extracting text from PDF.',
error: error.message,
});
}
}
Код: Выделить всё
const overlays: Overlay[] = projectResponse.data.components
.filter((c: any) => c && c.overlay && c.key && c.type)
.map((c: any) => ({
type: coerceType(c.type),
key: c.key,
label: c.label ?? "",
overlay: {
width: Number(c.overlay.width),
height: Number(c.overlay.height),
top: Number(c.overlay.top),
left: Number(c.overlay.left),
page: Number(c.overlay.page),
},
input: Boolean(c.input),
tableView: Boolean(c.tableView),
}));
Код: Выделить всё
{
type: 'textfield',
key: 'textboxes4',
label: 'Character Boxes',
overlay: { width: 361.393, height: 27.6432, top: 1154, left: 594, page: 1 },
{
type: 'textfield',
key: 'textboxes3-ext',
label: 'Text Field',
overlay: { width: 253.698, height: 21.8229, top: 1010, left: 282, page: 1 },
input: true,
tableView: true
}
Код: Выделить всё
{
type: 'characterbox', (this is what i needed)
key: 'textboxes4',
label: 'Character Boxes',
overlay: { width: 361.393, height: 27.6432, top: 1154, left: 594, page: 1 },
{
type: 'textfield',
key: 'textboxes3-ext',
label: 'Text Field',
overlay: { width: 253.698, height: 21.8229, top: 1010, left: 282, page: 1 },
input: true,
tableView: true
}
- Рекомендации по поддержке пользовательского типа () наряду с существующими типами
Код: Выделить всё
textbox - Как надежно обнаружить блоки символов:
по метке (, "box")Код: Выделить всё
"character" - или по размерам наложения (широкий + короткий по высоте)
Подробнее здесь: https://stackoverflow.com/questions/798 ... s-and-prev