Java Convertir PDF en Base64

1. Vue d'ensemble

Dans ce court didacticiel, nous verrons comment effectuer l'encodage et le décodage Base64 d'un fichier PDF à l'aide de Java 8 et Apache Commons Codec .

Mais d'abord, jetons un rapide coup d'œil aux bases de Base64.

2. Principes de base de Base64

Lors de l'envoi de données sur le fil, nous devons les envoyer au format binaire. Mais si nous n'envoyons que des 0 et des 1, différents protocoles de couche de transport peuvent les interpréter différemment et nos données peuvent être corrompues en vol.

Ainsi, pour avoir la portabilité et des normes communes lors du transfert de données binaires, Base64 est venu dans l'image .

Étant donné que l'expéditeur et le destinataire comprennent et ont accepté d'utiliser la norme, la probabilité que nos données soient perdues ou mal interprétées est considérablement réduite.

Voyons maintenant quelques façons d'appliquer cela à un PDF.

3. Conversion à l'aide de Java 8

À partir de Java 8, nous avons un utilitaire java.util.Base64 qui fournit des encodeurs et des décodeurs pour le schéma d'encodage Base64. Il prend en charge les types Basic, URL safe et MIME comme spécifié dans RFC 4648 et RFC 2045.

3.1. Codage

Pour convertir un PDF en Base64, nous devons d'abord l'obtenir en octets et le transmettre via la méthode d' encodage de java.util.Base64.Encoder :

byte[] inFileBytes = Files.readAllBytes(Paths.get(IN_FILE)); byte[] encoded = java.util.Base64.getEncoder().encode(inFileBytes);

Ici, IN_FILE est le chemin vers notre PDF d'entrée.

3.2. Encodage en continu

Pour les fichiers plus volumineux ou les systèmes avec une mémoire limitée, il est beaucoup plus efficace d'effectuer l'encodage à l'aide d'un flux au lieu de lire toutes les données en mémoire . Voyons comment y parvenir:

try (OutputStream os = java.util.Base64.getEncoder().wrap(new FileOutputStream(OUT_FILE)); FileInputStream fis = new FileInputStream(IN_FILE)) { byte[] bytes = new byte[1024]; int read; while ((read = fis.read(bytes)) > -1) { os.write(bytes, 0, read); } }

Ici, IN_FILE est le chemin vers notre PDF d'entrée, et OUT_FILE est le chemin vers un fichier contenant le document encodé en Base64. Au lieu de lire l'intégralité du PDF en mémoire, puis d'encoder le document complet en mémoire, nous lisons jusqu'à 1 Ko de données à la fois et transmettons ces données via l'encodeur dans OutputStream .

3.3. Décodage

A la réception, nous obtenons le fichier encodé.

Nous devons donc maintenant le décoder pour récupérer nos octets d'origine et les écrire dans un FileOutputStream pour obtenir le PDF décodé :

byte[] decoded = java.util.Base64.getDecoder().decode(encoded); FileOutputStream fos = new FileOutputStream(OUT_FILE); fos.write(decoded); fos.flush(); fos.close();

Ici, OUT_FILE est le chemin vers notre PDF à créer.

4. Conversion à l'aide d'Apache Commons

Ensuite, nous utiliserons le package Apache Commons Codec pour réaliser la même chose. Il est basé sur la RFC 2045 et est antérieur à l'implémentation de Java 8 dont nous avons parlé précédemment. Ainsi, lorsque nous devons prendre en charge plusieurs versions de JDK (y compris les anciennes) ou fournisseurs, cela s'avère pratique en tant qu'API tierce.

4.1. Maven

Pour pouvoir utiliser la bibliothèque Apache, nous devons ajouter une dépendance à notre pom.xml :

 commons-codec commons-codec 1.14  

La dernière version de ce qui précède est disponible sur Maven Central.

4.2. Codage

Les étapes sont les mêmes que pour Java 8, sauf que cette fois, nous transmettons nos octets d'origine à la méthode encodeBase64 de la classe org.apache.commons.codec.binary.Base64 :

byte[] inFileBytes = Files.readAllBytes(Paths.get(IN_FILE)); byte[] encoded = org.apache.commons.codec.binary.Base64.encodeBase64(inFileBytes); 

4.3. Encodage en continu

Le codage en continu n'est pas pris en charge par cette bibliothèque.

4.4. Décodage

Encore une fois, nous appelons simplement la méthode decodeBase64 et écrivons le résultat dans un fichier:

byte[] decoded = org.apache.commons.codec.binary.Base64.decodeBase64(encoded); FileOutputStream fos = new FileOutputStream(OUT_FILE); fos.write(decoded); fos.flush(); fos.close(); 

5. Test

Nous allons maintenant tester notre encodage et décodage en utilisant un simple test JUnit:

public class EncodeDecodeUnitTest { private static final String IN_FILE = // path to file to be encoded from; private static final String OUT_FILE = // path to file to be decoded into; private static byte[] inFileBytes; @BeforeClass public static void fileToByteArray() throws IOException { inFileBytes = Files.readAllBytes(Paths.get(IN_FILE)); } @Test public void givenJavaBase64_whenEncoded_thenDecodedOK() throws IOException { byte[] encoded = java.util.Base64.getEncoder().encode(inFileBytes); byte[] decoded = java.util.Base64.getDecoder().decode(encoded); writeToFile(OUT_FILE, decoded); assertNotEquals(encoded.length, decoded.length); assertEquals(inFileBytes.length, decoded.length); assertArrayEquals(decoded, inFileBytes); } @Test public void givenJavaBase64_whenEncodedStream_thenDecodedStreamOK() throws IOException { try (OutputStream os = java.util.Base64.getEncoder().wrap(new FileOutputStream(OUT_FILE)); FileInputStream fis = new FileInputStream(IN_FILE)) { byte[] bytes = new byte[1024]; int read; while ((read = fis.read(bytes)) > -1) { os.write(bytes, 0, read); } } byte[] encoded = java.util.Base64.getEncoder().encode(inFileBytes); byte[] encodedOnDisk = Files.readAllBytes(Paths.get(OUT_FILE)); assertArrayEquals(encoded, encodedOnDisk); byte[] decoded = java.util.Base64.getDecoder().decode(encoded); byte[] decodedOnDisk = java.util.Base64.getDecoder().decode(encodedOnDisk); assertArrayEquals(decoded, decodedOnDisk); } @Test public void givenApacheCommons_givenJavaBase64_whenEncoded_thenDecodedOK() throws IOException { byte[] encoded = org.apache.commons.codec.binary.Base64.encodeBase64(inFileBytes); byte[] decoded = org.apache.commons.codec.binary.Base64.decodeBase64(encoded); writeToFile(OUT_FILE, decoded); assertNotEquals(encoded.length, decoded.length); assertEquals(inFileBytes.length, decoded.length); assertArrayEquals(decoded, inFileBytes); } private void writeToFile(String fileName, byte[] bytes) throws IOException { FileOutputStream fos = new FileOutputStream(fileName); fos.write(bytes); fos.flush(); fos.close(); } }

Comme nous pouvons le voir, nous avons d'abord lu les octets d'entrée dans une méthode @BeforeClass , et dans nos deux méthodes @Test , nous avons vérifié que:

  • les tableaux d'octets codés et décodés sont de longueurs différentes
  • inFileBytes et les tableaux d'octets décodés sont de la même longueur et ont le même contenu

Bien sûr, nous pouvons également ouvrir le fichier PDF décodé que nous avons créé et voir que le contenu est le même que le fichier que nous avons donné en entrée.

6. Conclusion

Dans ce rapide didacticiel, nous en avons appris davantage sur l'utilitaire Base64 de Java.

Nous avons également vu des exemples de code pour convertir un PDF en et à partir de Base64 à l'aide de Java 8 et Apache Commons Codec . Fait intéressant, l'implémentation JDK est beaucoup plus rapide que celle d'Apache.

Comme toujours, le code source est disponible sur sur GitHub.