Update file upload handling to use Busboy for improved efficiency

Replace Multer with Busboy for multipart/form-data parsing in the webhook endpoint, enhancing file handling and dependency management.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: cfbfe47c-0c9a-4ebf-8a41-2937407eccff
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/cfbfe47c-0c9a-4ebf-8a41-2937407eccff/0kKwZtc
This commit is contained in:
michaelschal committed 2025-09-03 09:37:05 +00:00
1 parent fdbbb14a4f
commit caee73e16b
5 files changed
+284 -121

No files matched your search

+60 -18
View File
@@ -49,11 +49,9 @@ import { eq, desc, or, isNull } from "drizzle-orm";
import { invoiceVerificationService } from "./invoiceVerification";
import { backupService } from "./backupService";
import { weatherService } from "./weatherService.js";
import multer from "multer";
import Busboy from 'busboy';
import fetch from "node-fetch";
const upload = multer({ storage: multer.memoryStorage() });
export async function registerRoutes(app: Express): Promise<Server> {
// Detect environment
const environment = process.env.NODE_ENV || 'development';
@@ -72,16 +70,66 @@ export async function registerRoutes(app: Express): Promise<Server> {
await setupAuth(app);
// Route BAP pour envoi webhook n8n
app.post('/api/bap/send-webhook', isAuthenticated, upload.single('pdf'), async (req: any, res) => {
app.post('/api/bap/send-webhook', isAuthenticated, async (req: any, res) => {
try {
const { recipient } = req.body;
const file = req.file;
// Vérifier que l'utilisateur est admin
const user = await storage.getUser(req.user.claims ? req.user.claims.sub : req.user.id);
if (!user || user.role !== 'admin') {
return res.status(403).json({ error: 'Accès refusé - Admin uniquement' });
}
if (!file) {
// Parser le multipart/form-data avec busboy
const busboy = Busboy({ headers: req.headers });
let fileBuffer: Buffer | null = null;
let fileName = '';
let recipient = '';
let mimeType = '';
const parsePromise = new Promise<void>((resolve, reject) => {
busboy.on('file', (fieldname, file, info) => {
const { filename, mimeType: fileMimeType } = info;
if (fieldname === 'pdf') {
fileName = filename;
mimeType = fileMimeType;
const chunks: Buffer[] = [];
file.on('data', (chunk) => {
chunks.push(chunk);
});
file.on('end', () => {
fileBuffer = Buffer.concat(chunks);
});
} else {
file.resume(); // Ignorer les autres fichiers
}
});
busboy.on('field', (fieldname, val) => {
if (fieldname === 'recipient') {
recipient = val;
}
});
busboy.on('finish', () => {
resolve();
});
busboy.on('error', (err) => {
reject(err);
});
});
req.pipe(busboy);
await parsePromise;
// Valider les données
if (!fileBuffer) {
return res.status(400).json({ error: 'Aucun fichier PDF fourni' });
}
if (file.mimetype !== 'application/pdf') {
if (mimeType !== 'application/pdf') {
return res.status(400).json({ error: 'Le fichier doit être un PDF' });
}
@@ -89,24 +137,18 @@ export async function registerRoutes(app: Express): Promise<Server> {
return res.status(400).json({ error: 'Destinataire invalide' });
}
// Vérifier que l'utilisateur est admin
const user = await storage.getUser(req.user.claims ? req.user.claims.sub : req.user.id);
if (!user || user.role !== 'admin') {
return res.status(403).json({ error: 'Accès refusé - Admin uniquement' });
}
console.log('📤 BAP: Envoi webhook n8n', {
recipient,
fileName: file.originalname,
fileSize: file.size,
fileName,
fileSize: fileBuffer?.length || 0,
userId: user.id
});
// Créer FormData pour l'envoi vers n8n
const FormData = (await import('form-data')).default;
const formData = new FormData();
formData.append('pdf', file.buffer, {
filename: file.originalname,
formData.append('pdf', fileBuffer, {
filename: fileName,
contentType: 'application/pdf'
});
formData.append('recipient', recipient);