Java Конвертиране на PDF в Base64

1. Общ преглед

В този кратък урок ще видим как да направим Base64 кодиране и декодиране на PDF файл с помощта на Java 8 и Apache Commons Codec .

Но първо, нека да надникнем набързо в основите на Base64.

2. Основи на Base64

Когато изпращаме данни по кабел, трябва да ги изпращаме в двоичен формат. Но ако изпратим само 0 и 1, различните протоколи от транспортния слой може да ги интерпретират по различен начин и данните ни могат да се повредят по време на полет.

И така, за да има преносимост и общи стандарти при прехвърляне на двоични данни, Base64 дойде на снимката .

Тъй като изпращачът и получателят разбират и са се съгласили да използват стандарта, вероятността данните ни да се загубят или да бъдат изтълкувани погрешно е значително намалена.

Сега нека видим няколко начина да приложим това към PDF.

3. Преобразуване с помощта на Java 8

Започвайки с Java 8, имаме помощна програма java.util.Base64, която осигурява кодери и декодери за схемата за кодиране Base64. Той поддържа Basic, URL safe и MIME типове, както е посочено в RFC 4648 и RFC 2045.

3.1. Кодиране

За да преобразувате PDF в Base64, ние първо трябва да го получите в байтове и тя преминава през java.util.Base64.Encoder е кодиране метод :

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

Тук IN_FILE е пътят към нашия входен PDF файл.

3.2. Кодиране на поточно предаване

За по-големи файлове или системи с ограничена памет е много по-ефективно да се извърши кодирането с помощта на поток, вместо да се четат всички данни в паметта . Нека да разгледаме как да постигнем това:

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

Тук IN_FILE е пътят към нашия входен PDF файл, а OUT_FILE е пътят към файл, съдържащ кодирания в Base64 документ. Вместо да четем целия PDF в паметта и след това да кодираме пълния документ в паметта, ние четем до 1Kb данни наведнъж и ги предаваме през енкодера в OutputStream .

3.3. Декодиране

В края на получаването получаваме кодирания файл.

Така че сега трябва да го декодираме, за да си върнем оригиналните байтове и да ги запишем във FileOutputStream, за да получим декодирания PDF :

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

Тук OUT_FILE е пътят към нашия PDF, който трябва да бъде създаден.

4. Преобразуване с помощта на Apache Commons

След това ще използваме пакета Apache Commons Codec, за да постигнем същото. Той се основава на RFC 2045 и предшества внедряването на Java 8, което обсъдихме по-рано. Така че, когато трябва да поддържаме множество версии на JDK (включително наследени) или доставчици, това е полезно като API на трета страна.

4.1. Мейвън

За да можем да използваме библиотеката Apache, трябва да добавим зависимост към нашия pom.xml :

 commons-codec commons-codec 1.14  

Последната версия на горното може да бъде намерена на Maven Central.

4.2. Кодиране

Стъпките са същите, както за Java 8, с изключение на този път, ние минаваме на нашите оригинални байта към encodeBase64 метода на 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. Кодиране на поточно предаване

Кодирането на поточно предаване не се поддържа от тази библиотека.

4.4. Декодиране

Отново просто извикваме метода decodeBase64 и записваме резултата във файл:

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

5. Тестване

Сега ще тестваме нашето кодиране и декодиране с помощта на прост 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(); } }

Както виждаме, първо прочетохме входните байтове в метод @BeforeClass и в двата ни метода @Test проверихме, че:

  • кодираните и декодираните байтови масиви са с различна дължина
  • inFileBytes и декодираните байтови масиви са с еднаква дължина и имат същото съдържание

Разбира се, можем също да отворим декодирания PDF файл, който създадохме, и да видим, че съдържанието е същото като файла, който дадохме като вход.

6. Заключение

В този бърз урок научихме повече за помощната програма Base64 на Java.

Видяхме и примерни кодове за конвертиране на PDF в и от Base64 с помощта на Java 8 и Apache Commons Codec . Интересното е, че внедряването на JDK е много по-бързо от това на Apache.

Както винаги, изходният код е достъпен в GitHub.