Java Convertir PDF a Base64

1. Información general

En este breve tutorial, veremos cómo codificar y decodificar en Base64 un archivo PDF usando Java 8 y Apache Commons Codec .

Pero primero, echemos un vistazo rápido a los conceptos básicos de Base64.

2. Conceptos básicos de Base64

Al enviar datos por cable, debemos enviarlos en formato binario. Pero si enviamos solo 0 y 1, diferentes protocolos de la capa de transporte pueden interpretarlos de manera diferente y nuestros datos pueden corromperse durante el vuelo.

Entonces, para tener portabilidad y estándares comunes al transferir datos binarios, Base64 entró en escena .

Dado que tanto el remitente como el receptor entienden y han acordado utilizar el estándar, la probabilidad de que nuestros datos se pierdan o se malinterpreten se reduce considerablemente.

Ahora veamos un par de formas de aplicar esto a un PDF.

3. Conversión con Java 8

Comenzando con Java 8, tenemos una utilidad java.util.Base64 que proporciona codificadores y decodificadores para el esquema de codificación Base64. Admite los tipos Básico, seguro para URL y MIME como se especifica en RFC 4648 y RFC 2045.

3.1. Codificación

Para convertir un PDF en base 64, que primero tiene que conseguir que en bytes y pasarla a través java.util.Base64.Encoder 's codificar método :

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

Aquí, IN_FILE es la ruta a nuestro PDF de entrada.

3.2. Codificación de transmisión

Para archivos más grandes o sistemas con memoria limitada, es mucho más eficiente realizar la codificación usando una secuencia en lugar de leer todos los datos en la memoria . Veamos cómo lograr esto:

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

Aquí, IN_FILE es la ruta a nuestro PDF de entrada y OUT_FILE es la ruta a un archivo que contiene el documento codificado en Base64. En lugar de leer todo el PDF en la memoria y luego codificar el documento completo en la memoria, estamos leyendo hasta 1 Kb de datos a la vez y pasando esos datos a través del codificador al OutputStream .

3.3. Descodificación

En el extremo receptor, obtenemos el archivo codificado.

Así que ahora necesitamos decodificarlo para recuperar nuestros bytes originales y escribirlos en un FileOutputStream para obtener el PDF decodificado :

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

Aquí, OUT_FILE es la ruta a nuestro PDF que se creará.

4. Conversión mediante Apache Commons

A continuación, usaremos el paquete Apache Commons Codec para lograr lo mismo. Se basa en RFC 2045 y es anterior a la implementación de Java 8 que discutimos anteriormente. Entonces, cuando necesitamos admitir múltiples versiones de JDK (incluidas las heredadas) o proveedores, esto es útil como API de terceros.

4.1. Maven

Para poder usar la biblioteca de Apache, necesitamos agregar una dependencia a nuestro pom.xml :

 commons-codec commons-codec 1.14  

La última versión de lo anterior se puede encontrar en Maven Central.

4.2. Codificación

Los pasos son los mismos que para Java 8, excepto que esta vez, pasamos nuestros bytes originales al método encodeBase64 de la clase 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. Codificación de transmisión

Esta biblioteca no admite la codificación de transmisión.

4.4. Descodificación

Nuevamente, simplemente llamamos al método decodeBase64 y escribimos el resultado en un archivo:

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

5. Prueba

Ahora probaremos nuestra codificación y decodificación usando una prueba JUnit simple:

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

Como podemos ver, primero leemos los bytes de entrada en un método @BeforeClass , y en nuestros dos métodos @Test , verificamos que:

  • Las matrices de bytes codificadas y decodificadas tienen diferentes longitudes
  • inFileBytes y las matrices de bytes decodificadas son de la misma longitud y tienen el mismo contenido

Por supuesto, también podemos abrir el archivo PDF decodificado que creamos y ver que el contenido es el mismo que el archivo que le dimos como entrada.

6. Conclusión

En este tutorial rápido, aprendimos más sobre la utilidad Base64 de Java.

También vimos ejemplos de código para convertir un PDF en y desde Base64 usando Java 8 y Apache Commons Codec . Curiosamente, la implementación de JDK es mucho más rápida que la de Apache.

Como siempre, el código fuente está disponible en GitHub.