Java Converti PDF in Base64

1. Panoramica

In questo breve tutorial, vedremo come eseguire la codifica e la decodifica Base64 di un file PDF utilizzando Java 8 e Apache Commons Codec .

Ma prima, diamo una rapida occhiata alle basi di Base64.

2. Nozioni di base su Base64

Quando si inviano dati in rete, è necessario inviarli in formato binario. Ma se inviamo solo 0 e 1, diversi protocolli del livello di trasporto potrebbero interpretarli in modo diverso ei nostri dati potrebbero essere danneggiati durante il volo.

Quindi, per avere portabilità e standard comuni durante il trasferimento di dati binari, Base64 è entrato in scena .

Poiché il mittente e il destinatario hanno compreso e concordato l'utilizzo dello standard, la probabilità che i nostri dati vadano persi o vengano interpretati erroneamente è notevolmente ridotta.

Ora vediamo un paio di modi per applicarlo a un PDF.

3. Conversione tramite Java 8

A partire da Java 8, abbiamo un'utilità java.util.Base64 che fornisce codificatori e decodificatori per lo schema di codifica Base64. Supporta i tipi Basic, URL safe e MIME come specificato in RFC 4648 e RFC 2045.

3.1. Codifica

Per convertire un PDF in Base64, dobbiamo prima ottenerlo in byte e passarlo attraverso il metodo di codifica java.util.Base64.Encoder :

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

Qui, IN_FILE è il percorso del nostro PDF di input.

3.2. Codifica streaming

Per file o sistemi più grandi con memoria limitata, è molto più efficiente eseguire la codifica utilizzando un flusso invece di leggere tutti i dati in memoria . Diamo un'occhiata a come ottenere ciò:

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); } }

Qui, IN_FILE è il percorso del nostro PDF di input e OUT_FILE è il percorso di un file contenente il documento con codifica Base64. Invece di leggere l'intero PDF in memoria e quindi codificare l'intero documento in memoria, stiamo leggendo fino a 1Kb di dati alla volta e trasferendoli attraverso il codificatore nell'OutputStream .

3.3. Decodifica

All'estremità ricevente, otteniamo il file codificato.

Quindi ora dobbiamo decodificarlo per recuperare i nostri byte originali e scriverli in un FileOutputStream per ottenere il PDF decodificato :

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

Qui, OUT_FILE è il percorso del nostro PDF da creare.

4. Conversione utilizzando Apache Commons

Successivamente, utilizzeremo il pacchetto Apache Commons Codec per ottenere lo stesso risultato. È basato su RFC 2045 e precede l'implementazione di Java 8 di cui abbiamo discusso in precedenza. Quindi, quando dobbiamo supportare più versioni JDK (comprese quelle legacy) o fornitori, questo è utile come API di terze parti.

4.1. Esperto di

Per poter utilizzare la libreria Apache, dobbiamo aggiungere una dipendenza al nostro pom.xml :

 commons-codec commons-codec 1.14  

L'ultima versione di quanto sopra può essere trovata su Maven Central.

4.2. Codifica

I passaggi sono gli stessi di Java 8, tranne per il fatto che questa volta passiamo i nostri byte originali al metodo encodeBase64 della 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. Codifica streaming

La codifica in streaming non è supportata da questa libreria.

4.4. Decodifica

Ancora una volta, chiamiamo semplicemente il metodo decodeBase64 e scriviamo il risultato in un file:

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

Ora testeremo la nostra codifica e decodifica utilizzando un semplice 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(); } }

Come possiamo vedere, abbiamo prima letto i byte di input in un metodo @BeforeClass e in entrambi i nostri metodi @Test abbiamo verificato che:

  • gli array di byte codificati e decodificati hanno lunghezze diverse
  • inFileByte e gli array di byte decodificati hanno la stessa lunghezza e hanno lo stesso contenuto

Naturalmente, possiamo anche aprire il file PDF decodificato che abbiamo creato e vedere che i contenuti sono gli stessi del file che abbiamo fornito come input.

6. Conclusione

In questo breve tutorial, abbiamo imparato di più sull'utilità Base64 di Java.

Abbiamo anche visto esempi di codice per convertire un PDF in e da Base64 utilizzando Java 8 e Apache Commons Codec . È interessante notare che l'implementazione di JDK è molto più veloce di quella di Apache.

Come sempre, il codice sorgente è disponibile su GitHub.