Bonjour à tous,

Aprés des jours à galérer et à ne pas trouver, je vais m'en résoudre à la connaissance de la communauté.

Pour info, je fais ca par pur hobbit, donc mon développement et la structure de mon projet n'est pas trés conventionnel, je vous prie de bien vouloir être indulgeant.

Alors pour faire simple, j'ai une page reste_a_livrer.php dans lequel j'ai un appel AJAX pour mettre a jour mon tableau en fonction des paramètres de recherche.

Une fois cette appel AJAX fait (et mon tableau avec mes nouvelles données), j'ai la possibilité de cocher des lignes et de générer des PDF qui doivent s'enregistrer dans un dossier de mon projet, et c'est la ou est le problème :( Mes pdf sont généré avec la bibliothèque jsPDF

Dans un premier temps j'ai tous fait en PHP/JS et j'arrive bien a générer les PDF. Mais après consultation de divers forum/chatGPT/... je me suis apecu qu'il fallait passer par un server node.js, afin d'enregistrer sur le serveur, car jsPDF étant une bibliothèque JS, elle s'exécute coté client et moi je veux enregistrer coté serveur.

Arborescence de mes fichiers :

/pages/reste_a_livrer.php
/include/get_ral.php
/include/main.js
/include/serverNode.js
J'ai donc suivi moulte tuto pour en arriver au code ci-dessous, qui malheureusement me retourne en boucle les mêmes erreur dans la console :

Erreur 1 : POST http://127.0.0.1:8080/bvs/html/app-dev/include/savePdf : 404 not found

Erreur 2 :

Voila une partie de mon code mon code de reste_a_livrer.php

<div id="action" class="col-2" style="display : none ;">
<p id="titre_xs">Actions</p>
<a href="#" id="export_pdf_select" data-title="Titre du PDF ici"><p style="font-size: 11px;"><img src="../images/pdf.png" height=20 width=20/> Export PDF</p></a>
<a href="#" id="export_excel_select"><p style="font-size: 11px;"><img src="../images/excel.png" height=20 width=20 /> Export Excel</p></a>
<a href="#" id="envoi_mail_select"><p style="font-size: 11px;"><img src="../images/mail.png" height=20 width=20/> Envoi mail</p></a>
</div>
<div id="ResultRal" style="display : none;">
<table id="tabResultRal">
</table>
</div>
et mon code JS dans le meme fichier :

//Génération PDF unique
$(document).on('click', '#ral_client_pdf', function() {
var loadingModal = $('#loadingModal');
var client = $(this).data('parametre1');
var nomClient = $(this).data('parametre2');
var langue = $(this).data('parametre3');
var type_vente = $("input[type=radio][name=type_vente]:checked").val();
var stock = $("input[type=radio][name=stock]:checked").val();
var paiment = $("input[type=radio][name=paiement]:checked").val();
var traitementRandom = document.getElementById('traitementRandom').value;
var dateActuelle = new Date();

// Obtenez le jour, le mois et l'année de la date actuelle
var jour = dateActuelle.getDate();
var mois = dateActuelle.getMonth() + 1; // Les mois commencent à 0, donc ajoutez 1
var annee = dateActuelle.getFullYear();

// Formattez les composants de la date au format "JJ-MM-AAAA" (ajoutez des zéros pour les valeurs < 10 si nécessaire)
var dateFormatee = (jour < 10 ? '0' : '') + jour + '-' + (mois < 10 ? '0' : '') + mois + '-' + annee;
var tableSelector = "#tabResultRal";
var traitementRandom = document.getElementById('traitementRandom').value;
var titreExport = nomClient+"\nRESTE A LIVRER | " + dateFormatee;
    if(langue != "FR"){
        var titreExport =  nomClient+"\nPENDING ORDERS | " + dateFormatee;
    }

var data = {
    client: client,
    type_vente: type_vente,
    stock: stock,
    paiment: paiment,
    numTraitement: traitementRandom
};
loadingModal.show();
$.ajax({
    url: '../include/get_ral_client.php', // Remplacez par l'URL de votre requête serveur
    type: 'GET',
    data: data,
    success: function(response) {
        loadingModal.hide();
        $('#ResultRal').html(response);

        // Récupérer le nombre de résultats
        var numResults = $('#tabResultRal tbody tr').length;
        /*if (numResults > 0) {
            generatePDF(tableSelector, titreExport, titreExport)
        } else {
            alert('Aucune ligne de reste à livrer');
        }*/
    }
});

});

$(document).on('click', '#export_pdf_select', async function() {
var loadingModal = $('#loadingModal');
var type_vente = $("input[type=radio][name=type_vente]:checked").val();
var stock = $("input[type=radio][name=stock]:checked").val();
var paiment = $("input[type=radio][name=paiement]:checked").val();
var traitementRandom = document.getElementById('traitementRandom').value;
var dateActuelle = new Date();

// Obtenez le jour, le mois et l'année de la date actuelle
var jour = dateActuelle.getDate();
var mois = dateActuelle.getMonth() + 1; // Les mois commencent à 0, donc ajoutez 1
var annee = dateActuelle.getFullYear();

// Formattez les composants de la date au format "JJ-MM-AAAA" (ajoutez des zéros pour les valeurs < 10 si nécessaire)
var dateFormatee = (jour < 10 ? '0' : '') + jour + '-' + (mois < 10 ? '0' : '') + mois + '-' + annee;

// Obtenez toutes les lignes cochées avec la classe .checkbox-ligne
var lignesCochées = $('.checkbox-ligne:checked');

// Vérifiez s'il y a au moins une ligne cochée
if (lignesCochées.length === 0) {
    alert('Aucune ligne cochée.');
    return;
}

// Fonction pour générer un PDF pour une ligne donnée
async function generatePDFForLine(client, nomClient, langue) {
    var titreExport = nomClient + "\nRESTE A LIVRER | " + dateFormatee;
    if (langue != "FR") {
        titreExport = nomClient + "\nPENDING ORDERS | " + dateFormatee;
    }

    var data = {
        client: client,
        type_vente: type_vente,
        stock: stock,
        paiment: paiment,
        numTraitement: traitementRandom,
    };
    const tableSelector = '#tabResultRal';
    console.log(JSON.stringify({ "#export_pdf_select", titreExport, titreExport }));
    try {
        const response = await fetch('../include/savePdf.js', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            mode: 'no-cors', // Ajoutez cette ligne pour autoriser CORS
            body: JSON.stringify({ tableSelector, titreExport, titreExport }),
        });

        const pdfData = await response.json();

        // Téléchargez le PDF généré
        const a = document.createElement('a');
        a.href = pdfData.pdfPath;
        a.download = `${exportFileName}.pdf`;
        a.click();
    } catch (error) {
        console.error('Erreur lors de la génération du PDF :', error);
    }
}

// Boucle à travers les lignes cochées et génère un PDF pour chacune
for (let i = 0; i < lignesCochées.length; i++) {
    var row = lignesCochées[i];
    var ligne = $(row).closest('tr');
    var ralClientElement = ligne.find('#ral_client');
    var client = ralClientElement.data('parametre1');
    var nomClient = ralClientElement.data('parametre2');
    var langue = ralClientElement.data('parametre3');

    await generatePDFForLine(client, nomClient, langue);
}

});
Mon serveur node.js

const express = require('express');
const cors = require('cors');
const app = express();
const fs = require('fs');
const jsPDF = require('jspdf');
const port = 8080; // Port sur lequel le serveur écoutera

// Configuration d'Express
app.use(cors()); // Ajoutez cette ligne pour activer CORS
app.use(express.static('public')); // Servez des fichiers statiques depuis le dossier 'public'
app.use(express.json());

// Middleware pour autoriser les requêtes CORS
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*'); // Permettre l'accès depuis n'importe quel domaine (à des fins de développement)
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
next();
});

// Middleware pour gérer les fichiers JavaScript sans extension
app.use((req, res, next) => {
if (req.path.endsWith('.js')) {
// Si l'URL se termine par .js, retirez l'extension
req.url = req.url.slice(0, -3);
}
next();
});

// Route pour générer et télécharger le PDF
app.post('/savePdf', (req, res) => {
const { tableSelector, title, exportFileName } = req.body;

// Utilisez la fonction generatePDF depuis pdfGenerator.js
pdfGenerator.generatePDF(tableSelector, title, exportFileName);

// Répondez au client avec le chemin du PDF généré
res.json({ pdfPath: /pdfs/${exportFileName}.pdf });
});

// Démarrage du serveur
app.listen(port, () => {
console.log(Le serveur est en écoute sur le port ${port});
});
et ma fonction pour générer les pdf

function generatePDF(tableSelector, title, exportFileName) {
const fs = require('fs');
const jsPDF = require('jspdf');
const doc = new jsPDF('l', 'pt', 'a4');
doc.setFont("Tahoma");
var y = 20;

var footer = function(data) {                   
    var text = "Bordeaux Vins Selection - 42 Avenue René Antoune, 33 320 Eysines - negoce@bvswine.com";
    var textWidth = doc.getStringUnitWidth(text) * doc.internal.getFontSize();
    var textX = 230;
    var pageX = doc.internal.pageSize.getWidth() - 50;

    doc.setFontSize(10);
    doc.text(text, textX, doc.internal.pageSize.height - 10);
};

doc.setLineWidth(2);
var imgData = 'data:image/png;base64,';

doc.addImage(imgData, 'JPEG', 10, 10, 200, 60);
doc.setFontSize(20);
doc.setTextColor(77, 86, 67);
doc.setFont("Tahoma");
doc.setFontStyle("bold");

var lines = doc.splitTextToSize(title, 2 * doc.internal.pageSize.getWidth() / 3);

// Calculer la largeur de la première ligne
var lineWidth1 = doc.getStringUnitWidth(lines[0]) * doc.internal.getFontSize();
// Calculer la largeur de la deuxième ligne
var lineWidth2 = doc.getStringUnitWidth(lines[1]) * doc.internal.getFontSize();

// Calculer la position x pour centrer le texte
var centerX = (doc.internal.pageSize.getWidth() / 2) + 95;
var textX1 = centerX - (lineWidth1 / 2);
var textX2 = centerX - (lineWidth2 / 2);

// Afficher les deux lignes centrées
doc.text(textX1, 40, lines[0]);
y += 20; // Ajustez la hauteur selon vos besoins
doc.text(textX2, 75, lines[1]);

var options = {
    html: tableSelector,
    startY: 90,
    theme: 'grid',
    styles: {
    font: 'Tahoma',
    halign: 'center',
    cellPadding: 4,
    },
    columnStyles: {
        0: {fontStyle: 'Tahoma', halign: 'center'},
        1: {fontStyle: 'Tahoma', halign: 'center'},
        2: {fontStyle: 'Tahoma', halign: 'center'},
        3: {fontStyle: 'Tahoma', halign: 'center'},
        4: {fontStyle: 'Tahoma', halign: 'center'},
        5: {fontStyle: 'Tahoma', halign: 'center'},
        6: {fontStyle: 'Tahoma', halign: 'center'},
    },
    headerStyles: {
    fillColor: [77, 86, 67],
    fontStyle: 'bold',
    fontSize: 13,
    halign: 'center',
    },
    didDrawPage: footer
};

doc.autoTable(options);

doc.save(exportFileName);

const pdfPath = `./pdfs/${exportFileName}.pdf`; // Enregistrez localement
fs.writeFileSync(pdfPath, doc.output());

console.log(`Le PDF a été enregistré sous ${pdfPath}`);

}
// Exportez la fonction si vous devez l'appeler depuis d'autres fichiers
export default { generatePDF };

Voila, je pense vous avoir donné toutes les informations, en espérant que quelqu'un comprenne mon probleme et me l'explique :)

Merci a tous

1 réponse


Trop de code désolé ce n'est pas évident d'aider, il faudrait synthétiser ton problème :(