feat: Traitement automatique des fichiers non traités
- Modification de listFolderResults pour détecter les fichiers non traités - Mise en pending automatique des fichiers sans résultats d'extraction - Fonction processDocument pour traiter les fichiers en arrière-plan - Fonction processFileInBackground pour le traitement asynchrone - Fonction removePendingFlag pour nettoyer les flags après traitement - Les fichiers non traités sont maintenant automatiquement traités Fixes: Fichiers non traités mis en pending et traités automatiquement Fixes: Traitement en arrière-plan des fichiers uploadés sans extraction
This commit is contained in:
parent
736637c5cd
commit
328d2584de
@ -267,81 +267,34 @@ function listFolderResults(folderHash) {
|
||||
|
||||
// Vérifier si ce fichier n'a pas déjà un résultat en cache
|
||||
const hasCacheResult = results.some(result => result.fileHash === fileHash)
|
||||
// Vérifier si ce fichier n'est pas déjà en pending
|
||||
const isAlreadyPending = pending.some(p => p.fileHash === fileHash)
|
||||
|
||||
if (!hasCacheResult) {
|
||||
// Créer un résultat minimal pour les fichiers non traités
|
||||
if (!hasCacheResult && !isAlreadyPending) {
|
||||
// Mettre le fichier en pending et le traiter automatiquement
|
||||
const filePath = path.join(uploadsPath, file)
|
||||
const stats = fs.statSync(filePath)
|
||||
|
||||
results.push({
|
||||
fileHash,
|
||||
document: {
|
||||
id: `doc-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
||||
fileName: file,
|
||||
mimeType: getMimeTypeFromExtension(path.extname(file)),
|
||||
fileSize: stats.size,
|
||||
uploadTimestamp: stats.mtime.toISOString()
|
||||
},
|
||||
classification: {
|
||||
documentType: 'Document',
|
||||
confidence: 0.0,
|
||||
subType: 'Non traité',
|
||||
language: 'fr',
|
||||
pageCount: 1
|
||||
},
|
||||
extraction: {
|
||||
text: {
|
||||
raw: '',
|
||||
processed: '',
|
||||
wordCount: 0,
|
||||
characterCount: 0,
|
||||
confidence: 0.0
|
||||
},
|
||||
entities: {
|
||||
persons: [],
|
||||
companies: [],
|
||||
addresses: [],
|
||||
financial: {
|
||||
amounts: [],
|
||||
totals: {},
|
||||
payment: {}
|
||||
},
|
||||
dates: [],
|
||||
contractual: {
|
||||
clauses: [],
|
||||
signatures: []
|
||||
},
|
||||
references: []
|
||||
}
|
||||
},
|
||||
metadata: {
|
||||
processing: {
|
||||
engine: '4NK_IA_Backend',
|
||||
version: '1.0.0',
|
||||
processingTime: '0ms',
|
||||
ocrEngine: 'none',
|
||||
nerEngine: 'none',
|
||||
preprocessing: {
|
||||
applied: false,
|
||||
reason: 'Fichier non traité'
|
||||
}
|
||||
},
|
||||
quality: {
|
||||
globalConfidence: 0.0,
|
||||
textExtractionConfidence: 0.0,
|
||||
entityExtractionConfidence: 0.0,
|
||||
classificationConfidence: 0.0
|
||||
}
|
||||
},
|
||||
status: {
|
||||
success: false,
|
||||
errors: ['Fichier non traité'],
|
||||
warnings: ['Aucune extraction effectuée'],
|
||||
timestamp: stats.mtime.toISOString()
|
||||
}
|
||||
})
|
||||
console.log(`[FOLDER] Fichier non traité détecté, mise en pending: ${file}`)
|
||||
|
||||
console.log(`[FOLDER] Fichier non traité ajouté: ${file}`)
|
||||
// Créer le flag pending
|
||||
const pendingData = {
|
||||
fileHash,
|
||||
fileName: file,
|
||||
folderHash,
|
||||
timestamp: new Date().toISOString(),
|
||||
status: 'processing'
|
||||
}
|
||||
|
||||
// Sauvegarder le flag pending
|
||||
createPendingFlag(folderHash, fileHash, pendingData)
|
||||
|
||||
// Ajouter à la liste des pending
|
||||
pending.push(pendingData)
|
||||
hasPending = true
|
||||
|
||||
// Traiter le fichier en arrière-plan
|
||||
processFileInBackground(filePath, fileHash, folderHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -349,6 +302,103 @@ function listFolderResults(folderHash) {
|
||||
return { results, pending, hasPending }
|
||||
}
|
||||
|
||||
// Fonction pour traiter un document (extraction de la logique de /api/extract)
|
||||
async function processDocument(filePath, fileHash) {
|
||||
const startTime = Date.now()
|
||||
|
||||
try {
|
||||
console.log(`[PROCESS] Début du traitement: ${filePath}`)
|
||||
|
||||
// Obtenir les informations du fichier
|
||||
const stats = fs.statSync(filePath)
|
||||
const ext = path.extname(filePath)
|
||||
const mimeType = getMimeTypeFromExtension(ext)
|
||||
|
||||
// Créer un objet file similaire à celui de multer
|
||||
const file = {
|
||||
path: filePath,
|
||||
originalname: path.basename(filePath),
|
||||
mimetype: mimeType,
|
||||
size: stats.size
|
||||
}
|
||||
|
||||
let ocrResult
|
||||
let result
|
||||
|
||||
// Si c'est un PDF, extraire le texte directement
|
||||
if (mimeType === 'application/pdf') {
|
||||
console.log(`[PROCESS] Extraction de texte depuis PDF...`)
|
||||
try {
|
||||
ocrResult = await extractTextFromPdf(filePath)
|
||||
console.log(`[PROCESS] Texte extrait du PDF: ${ocrResult.text.length} caractères`)
|
||||
} catch (error) {
|
||||
console.error(`[PROCESS] Erreur lors de l'extraction PDF:`, error.message)
|
||||
throw new Error(`Erreur lors de l'extraction PDF: ${error.message}`)
|
||||
}
|
||||
} else {
|
||||
// Pour les images, utiliser l'OCR avec préprocessing
|
||||
ocrResult = await extractTextFromImage(filePath)
|
||||
}
|
||||
|
||||
// Extraction NER
|
||||
const entities = extractEntitiesFromText(ocrResult.text)
|
||||
|
||||
// Mesure du temps de traitement
|
||||
const processingTime = Date.now() - startTime
|
||||
|
||||
// Génération du format JSON standard
|
||||
result = generateStandardJSON(file, ocrResult, entities, processingTime)
|
||||
|
||||
console.log(`[PROCESS] Traitement terminé en ${processingTime}ms`)
|
||||
return result
|
||||
|
||||
} catch (error) {
|
||||
console.error(`[PROCESS] Erreur lors du traitement:`, error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// Fonction pour traiter un fichier en arrière-plan
|
||||
async function processFileInBackground(filePath, fileHash, folderHash) {
|
||||
try {
|
||||
console.log(`[BACKGROUND] Début du traitement en arrière-plan: ${filePath}`)
|
||||
|
||||
// Traiter le document
|
||||
const result = await processDocument(filePath, fileHash)
|
||||
|
||||
// Sauvegarder le résultat dans le cache du dossier
|
||||
const success = saveJsonCacheInFolder(folderHash, fileHash, result)
|
||||
|
||||
if (success) {
|
||||
// Supprimer le flag pending
|
||||
removePendingFlag(folderHash, fileHash)
|
||||
console.log(`[BACKGROUND] Traitement terminé avec succès: ${fileHash}`)
|
||||
} else {
|
||||
console.error(`[BACKGROUND] Erreur lors de la sauvegarde du résultat: ${fileHash}`)
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(`[BACKGROUND] Erreur lors du traitement en arrière-plan:`, error)
|
||||
// Supprimer le flag pending même en cas d'erreur
|
||||
removePendingFlag(folderHash, fileHash)
|
||||
}
|
||||
}
|
||||
|
||||
// Fonction pour supprimer un flag pending
|
||||
function removePendingFlag(folderHash, fileHash) {
|
||||
try {
|
||||
const cachePath = path.join('cache', folderHash)
|
||||
const pendingFile = path.join(cachePath, `${fileHash}.pending`)
|
||||
|
||||
if (fs.existsSync(pendingFile)) {
|
||||
fs.unlinkSync(pendingFile)
|
||||
console.log(`[PENDING] Flag pending supprimé: ${fileHash}`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[PENDING] Erreur lors de la suppression du flag pending:`, error)
|
||||
}
|
||||
}
|
||||
|
||||
// Fonction pour vérifier si un fichier existe déjà par hash dans un dossier
|
||||
function findExistingFileByHash(hash, folderHash) {
|
||||
const folderPath = path.join('uploads', folderHash)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user