Bonjour,
Dans un rpg ile, le programme génère un code mime en utilisant la library BASE64 et la fonction base64_encode;
Le résultat est ensuite écrit dans un fichier UTF-8 dans l'IFS.
Dans certains cas où la cause est encore indéterminée, il n'est pas possible avec ce code mime de restituer le pdf original,
avec en résultat un pdf vide (mais avec le bon nombre de pages).
Le travail est lancé en ccsid 297.
Dans un même travail certains code mime sont "corrects" (donnent donc le pdf original) alors que d'autres sont "faux".
De plus l'encodage sur notre machine et sur celle d'un tiers sont différents mais reproduisent le même pdf.
Sauriez-vous si la version d'OS, le niveau de PTF sont à vérifier ? S'agirait-il de paramètres systèmes différents ?
Comment s'assurer qu'un code mime est correct ? (coder et décoder ou autre?)
merci d'avance,
Daniel GARCIA.
Données corrompues suite à l'encodage base 64
Re: Données corrompues suite à l'encodage base 64
Bonjour,
Je recommanderai aujourd'hui d'utiliser la fonction SQL d'encodage en base64 : https://www.ibm.com/docs/en/i/7.6.0?top ... e64-encode
La plupart du temps, les problèmes viennent de la gestion des CCSID ;
- à l'entrée dans la fonction : elle attend du binaire (*hex ou 65535). Si les données sont lues et stockées dans des variables CHAR avec un CCSID cela peut modifier la valeur avant encodage
- à la sortie : on récupère une CHAR qui ne contient que des caractères ASCII de base, vous pouvez normalement l'utiliser dans n'importe quel CCSID
- si vous écrivez sur l'IFS le résultat, voir le CCSID du fichier généré
- qui peut aussi être altéré lors du transport
Pour moi le CCSID du job a peu d'importance du moment que vous pouvez utiliser CAST en SQL ou indiquer un CCSID sur vos variables RPG si besoin
Je recommanderai aujourd'hui d'utiliser la fonction SQL d'encodage en base64 : https://www.ibm.com/docs/en/i/7.6.0?top ... e64-encode
La plupart du temps, les problèmes viennent de la gestion des CCSID ;
- à l'entrée dans la fonction : elle attend du binaire (*hex ou 65535). Si les données sont lues et stockées dans des variables CHAR avec un CCSID cela peut modifier la valeur avant encodage
- à la sortie : on récupère une CHAR qui ne contient que des caractères ASCII de base, vous pouvez normalement l'utiliser dans n'importe quel CCSID
- si vous écrivez sur l'IFS le résultat, voir le CCSID du fichier généré
- qui peut aussi être altéré lors du transport
Pour moi le CCSID du job a peu d'importance du moment que vous pouvez utiliser CAST en SQL ou indiquer un CCSID sur vos variables RPG si besoin
Nathanaël
Re: Données corrompues suite à l'encodage base 64
Bonjour M BONNET,
Merci pour votre réponse.
Je vais essayer d'encoder via les fonctions SQL,
Je mettrai le résultat sur le fil
Merci pour votre réponse.
Je vais essayer d'encoder via les fonctions SQL,
Je mettrai le résultat sur le fil
Re: Données corrompues suite à l'encodage base 64
Bonjour,
Pour que l'encodage fonctionne il faut que le code de base et le code d'arrivée soient tout le temps les mêmes.
Vous parlez du CCSID du job. Mais ce qui importe c'est le CCSID des champs en entrée et en sortie.
Nous avons personnellement des champs en CCSID 1147 (le même que 297 mais avec le symbole €) car notre système de base est en CCSID 1147, mais aussi des champs en CCSID 1208 (UTF-8) sur nos fichiers récents, car nos interfaces basculent en Web.
Autre chose à prendre en compte, le fichier en sortie.
Il existe, et il est bien défini en UTF-8 ? Là aussi, ce n'est pas toujours évident, plusieurs outils n'affichant pas le même résultat...
Si j'utilise la commande WRKLNK par exemple, le fichier apparait en code 1252 (Windows), alors que si je l'ouvre avec un éditeur dédié, il est bien défini avec un entête et des attributs UTF-8.
Pour ce qui est de générer des PDF, nous utilisons pour notre part l'outil dédié PDFLib.
C'est un peu lourd car il faut tout traiter en code, mais le résultat est toujours celui qu'on attend, avec une vitesse d'exécution fort appréciable, et pour un coût de licence raisonnable, quand on voit celui d'autres outils.
Pour que l'encodage fonctionne il faut que le code de base et le code d'arrivée soient tout le temps les mêmes.
Vous parlez du CCSID du job. Mais ce qui importe c'est le CCSID des champs en entrée et en sortie.
Nous avons personnellement des champs en CCSID 1147 (le même que 297 mais avec le symbole €) car notre système de base est en CCSID 1147, mais aussi des champs en CCSID 1208 (UTF-8) sur nos fichiers récents, car nos interfaces basculent en Web.
Autre chose à prendre en compte, le fichier en sortie.
Il existe, et il est bien défini en UTF-8 ? Là aussi, ce n'est pas toujours évident, plusieurs outils n'affichant pas le même résultat...
Si j'utilise la commande WRKLNK par exemple, le fichier apparait en code 1252 (Windows), alors que si je l'ouvre avec un éditeur dédié, il est bien défini avec un entête et des attributs UTF-8.
Pour ce qui est de générer des PDF, nous utilisons pour notre part l'outil dédié PDFLib.
C'est un peu lourd car il faut tout traiter en code, mais le résultat est toujours celui qu'on attend, avec une vitesse d'exécution fort appréciable, et pour un coût de licence raisonnable, quand on voit celui d'autres outils.
Re: Données corrompues suite à l'encodage base 64
Bonjour Hurri,
Merci pour votre retour.
J'ai, sur les conseils de Nathanaël utilisé les ordres de QSYS2.
J'ai créé un programme qui lit un pdf, encode en base 64 et créer un fichier UTF-8 en un seul ordre SQL,
J'ai créé un programme qui lit un pdf, encode en base 64 dans une zone en deux ordres SQL
pour ensuite stocker le résultat dans un fichier UTF-8 (ceci étant utile lorsqu'on veut intégrer le résultat base64 dans un fichier existant par ailleurs (exemple typique du moment, la facture ubl)
Je vous mets ci-dessous les sources de ces deux programmes et vais tâcher de passer cette discussion en résolu.
Merci encore à tous.
un seul ordre SQl de fichier pdf à fichier UTF-8 (Base64)
Le programme pour passer par une zone intermédiaire
Merci pour votre retour.
J'ai, sur les conseils de Nathanaël utilisé les ordres de QSYS2.
J'ai créé un programme qui lit un pdf, encode en base 64 et créer un fichier UTF-8 en un seul ordre SQL,
J'ai créé un programme qui lit un pdf, encode en base 64 dans une zone en deux ordres SQL
pour ensuite stocker le résultat dans un fichier UTF-8 (ceci étant utile lorsqu'on veut intégrer le résultat base64 dans un fichier existant par ailleurs (exemple typique du moment, la facture ubl)
Je vous mets ci-dessous les sources de ces deux programmes et vais tâcher de passer cette discussion en résolu.
Merci encore à tous.
un seul ordre SQl de fichier pdf à fichier UTF-8 (Base64)
Code : Tout sélectionner
**free
ctl-opt datedit(*DMY/) dftname(TSTBASE64) decedit('0,')
option(*srcstmt:*nodebugIO);
// Déclaration de variable
dcl-s Ret char(1);
// Déclaration des variables hôtes pour interagir avec le fichier IFS
dcl-s MonPdf_In sqltype(BLOB_FILE);
dcl-s MonB64_Out sqltype(CLOB_FILE);
// Chemin d'accès des fichiers sur l'IFS
dcl-s cheminPdfIn varchar(256);
dcl-s cheminTxtOut varchar(256);
// Initialisation
exec sql
set option commit = *none;
// Configuration des chemins
cheminPdfIn = '/home/garcida/felec/FactureTest11.pdf';
cheminTxtOut = '/home/garcida/felec/FactureTestMIME11.txt';
// -----------------------------------------------------------------
// 1. Configuration du fichier d'entrée (Le PDF binaire)
// -----------------------------------------------------------------
MonPdf_In_Name = %trim(cheminPdfIn);
MonPdf_In_NL = %len(%trim(MonPdf_In_Name));
MonPdf_In_FO = SQFRD; // SQFRD = Lecture seule (Read)
// -----------------------------------------------------------------
// 2. Configuration du fichier de sortie (Le texte encodé Base64)
// -----------------------------------------------------------------
MonB64_Out_Name = %trim(cheminTxtOut);
MonB64_Out_NL = %len(%trim(MonB64_Out_Name));
MonB64_Out_FO = SQFCRT; // SQFCRT = Créer/Écraser le fichier (Create)
// Execution du SQL pour encoder le fichier
exec sql
SET :MonB64_Out = QSYS2.BASE64_ENCODE(:MonPdf_In);
// Vérification du résultat
if SqlCode < 0;
// Une erreur est survenue lors du traitement SQL
// dsply ('Erreur SQL : ' + %char(SqlCode));
Ret = '0';
else;
// dsply 'Fichier PDF encodé en Base64 avec succès !';
Ret = '1';
endif;
*inLR = *On;
Return;
Code : Tout sélectionner
**free
ctl-opt dftactgrp(*no) actgrp('TEST') BndDir('QC2LE');
// Déclaration de la variable de référence de fichier SQL pour le PDF d'origine
dcl-s pdf_file varchar(256) Inz('/home/garcida/felec/factureTest11.pdf');
// Variable pour réceptionner la chaîne binaire récupérée lors de la lecture du fichier pdf
dcl-s Bin_Read sqltype(BLOB:32000); // Ajustez la taille max selon vos PDF
// Variable pour réceptionner la chaîne finale encodée en Base64
dcl-s base64_result sqltype(CLOB:45000); // Ajustez la taille max selon vos besoins
// Message d'erreur
dcl-s msgText varchar(32740); // Erreur SQL en clair
// Fonctions sur les fichiers IFS
// ==============================
// --- Ouverture d'un fichier
dcl-pr fOpen pointer ExtProc( '_C_IFS_fopen' ); //Renvoi handle fichier
*n pointer Value Options(*String); //Fichier (avec répertoire)
*n pointer Value Options(*String); //Mode ouverture
end-pr;
// --- Ecriture d'une ligne dans le fichier
dcl-pr fPutS int(10) ExtProc( '_C_IFS_fputs' ); //Renvoi code retour opération
*n pointer Value Options(*String); //Texte à enregistrer
*n pointer Value; //handle du fichier
end-pr;
// --- Fermeture d'un fichier
dcl-pr fClose int(10) ExtProc( '_C_IFS_fclose' ); //Renvoi code retour opération
*n pointer Value; //handle du fichier
end-pr;
//--- Suppression d'un fichier
dcl-pr unlink int(10) ExtProc( 'unlink' ); //Renvoi code retour opération
*n pointer Value Options(*String); //Fichier (avec répertoire)
end-pr;
// --- Infos fichier
dcl-s FILE_o pointer Inz(*null); //handle du fichier IFS
dcl-s String char(50000); //texte à écrire dans le fichier IFS
dcl-s rc int(10) Inz; //code retour à l'écriture et fermeture du fichier IFS
dcl-s NomFic varchar(256) Inz; //Nom du fichier à générer
// Moniteur des erreurs SQL
exec sql
whenever sqlerror do erreur_sql();
// 1. Lecture et encodage du PDF directement en SQL
exec sql
select line into :Bin_Read from table(QSYS2.IFS_READ_BINARY(:pdf_file));
// 2. Lecture et encodage du PDF directement en SQL
exec sql
Values QSYS2.BASE64_ENCODE(:Bin_Read)
into :base64_result;
// 3. Création d'un fichier en sortie (UTF-8)
// --- Nom du fichier à générer
Clear NomFic;
NomFic = '/home/garcida/felec/factureTestB6411.txt';
// --- Suppression du fichier précédent
rc = unlink( %trim(NomFic) );
// --- Création du fichier en écriture
FILE_o = fOPen(%trimr(NomFic):'w, o_ccsid=1208');
// --- Signaler l'erreur d'ouverture du fichier
If FILE_o = *Null;
dsply 'Erreur création fichier' ;
return ;
Endif;
rc = fClose(FILE_o);
FILE_o = fOPen(%trimr(NomFic):'w, o_ccsid=0');
// --- Ecriture avec conversion EBCDIC -> UTF-8
String = %trimr(base64_result_data);
rc = fPutS(%trimr(String):FILE_o);
// --- Fermeture du fichier
rc = fClose(FILE_o);
// Fin de programme
*inlr = *on;
return;
dcl-proc erreur_sql;
dcl-pi *n;
end-pi;
// Traitement des erreurs (Vérifiez le SQLCODE / SQLSTATE)
exec sql
GET DIAGNOSTICS CONDITION 1 :msgText = MESSAGE_TEXT;
return;
end-proc;