Java PDF를 Base64로 변환

1. 개요

이 짧은 튜토리얼에서는 Java 8 및 Apache Commons Codec을 사용하여 PDF 파일의 Base64 인코딩 및 디코딩을 수행하는 방법을 알아 봅니다 .

하지만 먼저 Base64의 기본 사항을 간단히 살펴 보겠습니다.

2. Base64의 기초

유선으로 데이터를 보낼 때 바이너리 형식으로 데이터를 보내야합니다. 그러나 0과 1 만 보내면 다른 전송 계층 프로토콜이이를 다르게 해석 할 수 있고 데이터가 비행 중에 손상 될 수 있습니다.

따라서 바이너리 데이터를 전송하는 동안 이식성과 공통 표준을 갖기 위해 Base64가 등장했습니다 .

발신자와 수신자가 모두 표준 사용을 이해하고 동의했기 때문에 데이터가 손실되거나 잘못 해석 될 가능성이 크게 줄어 듭니다.

이제 이것을 PDF에 적용하는 몇 가지 방법을 살펴 보겠습니다.

3. Java 8을 사용한 변환

Java 8부터는 Base64 인코딩 체계를위한 인코더와 디코더를 제공 하는 유틸리티 java.util.Base64 가 있습니다. RFC 4648 및 RFC 2045에 지정된대로 기본, URL 안전 및 MIME 유형을 지원합니다.

3.1. 부호화

PDF를 Base64로 변환하려면 먼저 바이트 단위로 가져 와서 java.util.Base64.Encoderencode 메소드를 통해 전달해야합니다 .

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. 디코딩

수신 측에서 인코딩 된 파일을 얻습니다.

따라서 이제 원래 바이트를 되찾기 위해이를 디코딩하고 디코딩 된 PDF를 가져 오기 위해 FileOutputStream 에 작성해야합니다 .

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과 동일하지만 이번에는 원래 바이트를 org.apache.commons.codec.binary.Base64 클래스 의 encodeBase64 메서드로 전달합니다 .

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. 결론

이 빠른 튜토리얼에서 우리는 Java의 Base64 유틸리티에 대해 자세히 배웠습니다.

또한 Java 8 및 Apache Commons Codec을 사용하여 PDF를 Base64로 변환하기 위한 코드 샘플도 보았습니다 . 흥미롭게도 JDK 구현은 Apache보다 훨씬 빠릅니다.

항상 그렇듯이 소스 코드는 GitHub에서 사용할 수 있습니다.