Improve and fix ProvaService.ts
Signed-off-by: Rodrigo Martins <rodrigo.sousa.577@gmail.com>
This commit is contained in:
1 parent
b764c93106
commit
c459997cd9
3 files changed
+106
-12
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import { createHash } from 'crypto';
|
||||
import sharp from 'sharp';
|
||||
|
||||
export class FileValidator {
|
||||
async validateFile(buffer: Buffer, mimeType: string) {
|
||||
@@ -18,7 +19,7 @@ export class FileValidator {
|
||||
const allowedTypes = [
|
||||
'application/pdf',
|
||||
'image/jpeg',
|
||||
'image/png', // Corrigido o tipo MIME para PNG
|
||||
'image/png',
|
||||
'image/gif',
|
||||
'image.webp'
|
||||
];
|
||||
@@ -27,6 +28,20 @@ export class FileValidator {
|
||||
return { valid: false, error: 'Tipo de arquivo não suportado. Use PDF, JPEG, PNG ou GIF.' };
|
||||
}
|
||||
|
||||
// Verificação adicional para JPEG
|
||||
if (mimeType === 'image/jpeg') {
|
||||
try {
|
||||
// Verificar se é um JPEG válido tentando processá-lo
|
||||
await sharp(buffer).metadata();
|
||||
} catch (jpegError) {
|
||||
console.error('Erro ao validar JPEG:', jpegError);
|
||||
return {
|
||||
valid: false,
|
||||
error: 'O arquivo JPEG parece estar corrompido. Tente salvar a imagem em um formato diferente e enviar novamente.'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { valid: true };
|
||||
} catch (error) {
|
||||
console.error('Erro na validação de arquivo:', error);
|
||||
|
||||
@@ -294,6 +294,18 @@ export class ProvaService {
|
||||
private async processFileByType(file: Express.Multer.File) {
|
||||
if (file.mimetype.startsWith('image/')) {
|
||||
try {
|
||||
// Para JPEGs, converter sempre para PNG para evitar problemas
|
||||
if (file.mimetype === 'image/jpeg') {
|
||||
return await sharp(file.buffer)
|
||||
.png() // Converter para PNG é mais seguro
|
||||
.resize(1200, 900, {
|
||||
fit: 'inside',
|
||||
withoutEnlargement: true
|
||||
})
|
||||
.toBuffer();
|
||||
}
|
||||
|
||||
// Para outras imagens, manter o formato original
|
||||
return await sharp(file.buffer)
|
||||
.resize(1200, 900, {
|
||||
fit: 'inside',
|
||||
@@ -302,7 +314,19 @@ export class ProvaService {
|
||||
.toBuffer();
|
||||
} catch (error) {
|
||||
console.error('Erro ao processar imagem com sharp:', error);
|
||||
return file.buffer; // Fallback para o buffer original
|
||||
|
||||
// Se sharp falhar, tentar abordagem mais simples
|
||||
try {
|
||||
console.log('Tentando método alternativo de processamento de imagem...');
|
||||
// Converter diretamente para PNG sem redimensionamento
|
||||
return await sharp(file.buffer)
|
||||
.png()
|
||||
.toBuffer();
|
||||
} catch (fallbackError) {
|
||||
console.error('Falha total no processamento da imagem:', fallbackError);
|
||||
// Em último caso, retornar o buffer original
|
||||
return file.buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return file.buffer;
|
||||
|
||||
@@ -5,6 +5,7 @@ import ptBR from 'date-fns/locale/pt-BR';
|
||||
import { prisma } from '../prismaClient';
|
||||
import * as fs from 'fs/promises';
|
||||
import * as path from 'path';
|
||||
import sharp from 'sharp';
|
||||
|
||||
export class ReportGenerator {
|
||||
async generateReport(data: {
|
||||
@@ -175,7 +176,7 @@ export class ReportGenerator {
|
||||
private async drawImagePage(page: any, data: any, helvetica: any, helveticaBold: any, pdfDoc: PDFDocument) {
|
||||
const height = page.getHeight();
|
||||
|
||||
// Título
|
||||
// Título e informações básicas (mantidos como estão)
|
||||
page.drawText('Documento Original', {
|
||||
x: 50,
|
||||
y: height - 50,
|
||||
@@ -184,7 +185,6 @@ export class ReportGenerator {
|
||||
color: rgb(0, 0, 0.7)
|
||||
});
|
||||
|
||||
// Informações básicas do arquivo
|
||||
page.drawText(`Arquivo: ${data.file.originalname}`, {
|
||||
x: 50,
|
||||
y: height - 80,
|
||||
@@ -192,7 +192,6 @@ export class ReportGenerator {
|
||||
font: helvetica
|
||||
});
|
||||
|
||||
// Formatação segura de data de registro
|
||||
let timestampStr = 'Data não disponível';
|
||||
try {
|
||||
if (data.timestamp?.timestamp) {
|
||||
@@ -212,7 +211,6 @@ export class ReportGenerator {
|
||||
font: helvetica
|
||||
});
|
||||
|
||||
// Data de modificação original
|
||||
if (data.metadata?.fileInfo?.modifiedDate || data.metadata?.file_specific?.modified) {
|
||||
const modifiedDate = new Date(data.metadata?.fileInfo?.modifiedDate || data.metadata?.file_specific?.modified);
|
||||
if (!isNaN(modifiedDate.getTime())) {
|
||||
@@ -225,15 +223,55 @@ export class ReportGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
// Incorporar a imagem
|
||||
// Incorporar a imagem com tratamento de erro mais robusto
|
||||
try {
|
||||
let image;
|
||||
let imageBuffer = data.file.buffer;
|
||||
|
||||
// Se for JPEG, tentar pré-processar com sharp para garantir um formato válido
|
||||
if (data.file.mimetype === 'image/jpeg') {
|
||||
image = await pdfDoc.embedJpg(data.file.buffer);
|
||||
} else if (data.file.mimetype === 'image/png') {
|
||||
try {
|
||||
// Converter para PNG primeiro - isso resolve muitos problemas de JPEGs corrompidos
|
||||
const processedBuffer = await sharp(data.file.buffer)
|
||||
.png() // Converter para PNG que é mais robusto
|
||||
.toBuffer();
|
||||
|
||||
// Usar PNG em vez de JPEG para evitar o erro SOI
|
||||
image = await pdfDoc.embedPng(processedBuffer);
|
||||
console.log('JPEG convertido para PNG para evitar problemas de formatação');
|
||||
} catch (sharpError) {
|
||||
console.error('Erro ao processar JPEG com sharp:', sharpError);
|
||||
|
||||
// Se falhar, tentar abordagem alternativa
|
||||
try {
|
||||
// Tentar usar a versão processada se disponível
|
||||
if (data.processedFile && data.processedFile.length > 0) {
|
||||
image = await pdfDoc.embedPng(data.processedFile);
|
||||
console.log('Usando versão processada da imagem');
|
||||
} else {
|
||||
throw new Error('Imagem processada não disponível');
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
console.error('Erro no fallback para imagem processada:', fallbackError);
|
||||
throw new Error('Não foi possível processar a imagem JPEG');
|
||||
}
|
||||
}
|
||||
}
|
||||
// Para PNG ou outros formatos
|
||||
else if (data.file.mimetype === 'image/png') {
|
||||
image = await pdfDoc.embedPng(data.file.buffer);
|
||||
} else {
|
||||
image = await pdfDoc.embedPng(data.processedFile);
|
||||
}
|
||||
// Para todos os outros tipos, tentar converter para PNG
|
||||
else {
|
||||
try {
|
||||
const pngBuffer = await sharp(data.file.buffer)
|
||||
.png()
|
||||
.toBuffer();
|
||||
image = await pdfDoc.embedPng(pngBuffer);
|
||||
} catch (conversionError) {
|
||||
console.error('Erro ao converter imagem para PNG:', conversionError);
|
||||
throw new Error('Formato de imagem não suportado');
|
||||
}
|
||||
}
|
||||
|
||||
// Calcular dimensões mantendo proporção
|
||||
@@ -286,13 +324,30 @@ export class ReportGenerator {
|
||||
});
|
||||
} catch (imageError) {
|
||||
console.error('Erro ao processar imagem:', imageError);
|
||||
|
||||
// Mensagem de erro mais informativa na página
|
||||
page.drawText('Não foi possível exibir a imagem original.', {
|
||||
x: 50,
|
||||
y: height / 2,
|
||||
y: height / 2 + 20,
|
||||
size: 14,
|
||||
font: helveticaBold,
|
||||
color: rgb(0.8, 0, 0)
|
||||
});
|
||||
|
||||
page.drawText(`Erro: ${imageError.message}`, {
|
||||
x: 50,
|
||||
y: height / 2 - 10,
|
||||
size: 12,
|
||||
font: helvetica,
|
||||
color: rgb(0.7, 0, 0)
|
||||
});
|
||||
|
||||
page.drawText('O documento foi validado, mas a visualização não está disponível.', {
|
||||
x: 50,
|
||||
y: height / 2 - 30,
|
||||
size: 12,
|
||||
font: helvetica
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user