fix: upgrade UDF text extraction with multi-offset PK search and binary noise filter
This commit is contained in:
@@ -421,16 +421,29 @@ export async function extractTextFromUploadedFile(file: { buffer: Buffer; mimety
|
|||||||
if (fileName.endsWith('.udf')) {
|
if (fileName.endsWith('.udf')) {
|
||||||
try {
|
try {
|
||||||
let zip: AdmZip | null = null;
|
let zip: AdmZip | null = null;
|
||||||
|
|
||||||
|
// 1. Önce doğrudan buffer üzerinden dene
|
||||||
try {
|
try {
|
||||||
zip = new AdmZip(file.buffer);
|
zip = new AdmZip(file.buffer);
|
||||||
} catch (e) {
|
if (zip.getEntries().length === 0) zip = null;
|
||||||
// PK\x03\x04 imzasını (0x50, 0x4B, 0x03, 0x04) buffer içinde ara (UYAP e-imza başlığı olan dosyalar için)
|
|
||||||
const pkSignature = Buffer.from([0x50, 0x4b, 0x03, 0x04]);
|
|
||||||
const pkIndex = file.buffer.indexOf(pkSignature);
|
|
||||||
if (pkIndex > 0) {
|
|
||||||
try {
|
|
||||||
zip = new AdmZip(file.buffer.subarray(pkIndex));
|
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|
||||||
|
// 2. Başarısız olursa PK\x03\x04 imzalarını (0x50, 0x4B, 0x03, 0x04) tüm buffer içinde tarayıp geçerli ZIP arşivini bul
|
||||||
|
if (!zip) {
|
||||||
|
const pkSignature = Buffer.from([0x50, 0x4b, 0x03, 0x04]);
|
||||||
|
let searchOffset = 0;
|
||||||
|
while (searchOffset < file.buffer.length) {
|
||||||
|
const pkIndex = file.buffer.indexOf(pkSignature, searchOffset);
|
||||||
|
if (pkIndex === -1) break;
|
||||||
|
try {
|
||||||
|
const testZip = new AdmZip(file.buffer.subarray(pkIndex));
|
||||||
|
const entries = testZip.getEntries();
|
||||||
|
if (entries && entries.length > 0) {
|
||||||
|
zip = testZip;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
|
searchOffset = pkIndex + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,7 +451,7 @@ export async function extractTextFromUploadedFile(file: { buffer: Buffer; mimety
|
|||||||
const zipEntries = zip.getEntries().filter((e: any) => !e.isDirectory);
|
const zipEntries = zip.getEntries().filter((e: any) => !e.isDirectory);
|
||||||
|
|
||||||
// 1. Önce XML dosyasını kontrol et (content.xml veya *.xml)
|
// 1. Önce XML dosyasını kontrol et (content.xml veya *.xml)
|
||||||
const xmlEntry = zipEntries.find((entry: any) =>
|
const xmlEntries = zipEntries.filter((entry: any) =>
|
||||||
entry.entryName === "content.xml" || entry.entryName.toLowerCase().endsWith(".xml")
|
entry.entryName === "content.xml" || entry.entryName.toLowerCase().endsWith(".xml")
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -447,16 +460,11 @@ export async function extractTextFromUploadedFile(file: { buffer: Buffer; mimety
|
|||||||
entry.entryName.toLowerCase().endsWith(".pdf")
|
entry.entryName.toLowerCase().endsWith(".pdf")
|
||||||
);
|
);
|
||||||
|
|
||||||
// Eğer XML bulunmuşsa XML üzerinden devam et
|
for (const xmlEntry of xmlEntries) {
|
||||||
if (xmlEntry) {
|
|
||||||
let rawXml = '';
|
let rawXml = '';
|
||||||
try {
|
try {
|
||||||
const entryBuffer = xmlEntry.getData();
|
const entryBuffer = xmlEntry.getData();
|
||||||
// UDF belgeleri UTF-8 veya ISO-8859-9 / Windows-1254 (Türkçe) kodlamasına sahip olabilir
|
|
||||||
rawXml = entryBuffer.toString('utf8');
|
rawXml = entryBuffer.toString('utf8');
|
||||||
if (rawXml.includes('encoding="ISO-8859-9"') || rawXml.includes('encoding="windows-1254"')) {
|
|
||||||
// iconv-lite or fallback string replacement if needed
|
|
||||||
}
|
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
rawXml = zip.readAsText(xmlEntry);
|
rawXml = zip.readAsText(xmlEntry);
|
||||||
}
|
}
|
||||||
@@ -469,8 +477,10 @@ export async function extractTextFromUploadedFile(file: { buffer: Buffer; mimety
|
|||||||
.replace(/ /g, " ")
|
.replace(/ /g, " ")
|
||||||
.replace(/\s+/g, " ")
|
.replace(/\s+/g, " ")
|
||||||
.trim();
|
.trim();
|
||||||
if (plainText.length > 20) {
|
|
||||||
return sanitizePostgresText(plainText);
|
const cleaned = sanitizePostgresText(plainText);
|
||||||
|
if (cleaned.length > 20 && !cleaned.startsWith('PK')) {
|
||||||
|
return cleaned;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -486,20 +496,25 @@ export async function extractTextFromUploadedFile(file: { buffer: Buffer; mimety
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ZIP çözülemediyse düz XML / metin olarak oku
|
// 3. ZIP çözülemediyse ham buffer içinden okunabilir Türkçe metin bloklarını çek (İkili çöp veriyi süz)
|
||||||
const rawText = file.buffer.toString('utf8');
|
const rawText = file.buffer.toString('utf8');
|
||||||
if (rawText && rawText.trim().length > 20) {
|
const textMatches = rawText.match(/[a-zA-Z0-9çğıöşüÇĞİÖŞÜ\s.,:;()\-]{15,}/g);
|
||||||
const plainText = rawText.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
if (textMatches && textMatches.length > 0) {
|
||||||
const cleaned = sanitizePostgresText(plainText);
|
const cleanExtracted = textMatches
|
||||||
if (cleaned.length > 20) {
|
.map(m => m.trim())
|
||||||
|
.filter(m => m.length > 15 && !m.includes('documentproperties') && !m.includes('sign.sgn') && !m.startsWith('PK'))
|
||||||
|
.join('\n');
|
||||||
|
|
||||||
|
const cleaned = sanitizePostgresText(cleanExtracted);
|
||||||
|
if (cleaned.length > 30) {
|
||||||
return cleaned;
|
return cleaned;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("UDF/ZIP arşivinde okunabilir XML veya PDF içeriği bulunamadı.");
|
throw new Error("UDF arşivinde okunabilir metin içeriği bulunamadı.");
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error("UDF parse error:", err);
|
console.error("UDF parse error:", err);
|
||||||
throw new Error(`UDF dosyası ayrıştırılamadı: ${err.message || 'Bozuk arşiv'}`);
|
throw new Error(`UDF dosyası ayrıştırılamadı: ${err.message || 'Bozuk veya şifreli dosya'}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user