Автор оригинала: Sampada Wagde.
1. Обзор
В этом коротком учебнике мы увидим как сделать Base64 кодирования и расшифровки файла PDF с помощью Java 8 и Apache Commons Codec .
Но сначала, давайте быстро взглянуть на основы Base64.
2. Основы базы64
При отправке данных по проводу, мы должны отправить его в двоичном формате. Но если мы отправим только 0 и 1, различные протоколы транспортного слоя могут интерпретировать их по-разному, и наши данные могут быть повреждены в полете.
Итак, иметь переносимость и общие стандарты при передаче бинарных данных, Base64 вошел в .
Поскольку отправитель и получатель понимают и договариваются об использовании стандарта, вероятность того, что наши данные будут потеряны или неправильно истолкованы, значительно снижается.
Теперь давайте посмотрим несколько способов применить это к PDF.
3. Преобразование с использованием Java 8
Начиная с Java 8, у нас есть утилита java.util.Base64 который предоставляет кодеры и декодеры для схемы кодирования Base64. Он поддерживает основные, URL безопасные и 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 данных за один раз и передачи этих данных через кодер в ВыходСтрим .
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, мы должны добавить зависимость к нашей пом.xml :
commons-codec commons-codec 1.14
Последнюю версию вышеуказанного можно найти на Мавен Центральный .
4.2. Кодирование
Шаги такие же, как для Java 8, за исключением того, что на этот раз, мы переходят на наши оригинальные байты кодироватьBase64 метод 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. Декодирование
Опять же, мы просто называем расшифроватьBase64 метод и написать результат в файл:
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 методы, подтвердили, что:
- закодированные и расшифрованые массивы byte разной длины
- inFileBytes и расшифрованые массивы byte имеют одинаковую длину и имеют одинаковое содержимое
Конечно, мы также можем открыть расшифрованные PDF-файл, который мы создали, и увидеть, что содержимое такое же, как файл, который мы дали в качестве ввода.
6. Заключение
В этом быстром учебнике мы узнали больше о утилите Java Base64.
Мы также видели образцы кода для преобразование PDF в и из Base64 с использованием Java 8 и Apache Commons Codec . Интересно, что реализация JDK намного быстрее, чем у Apache.
Как всегда, исходный код доступен более на GitHub .