Java将PDF转换为Base64

Java Convert PDF to Base64

1.概述

在这个简短的教程中,我们将看到如何使用Java 8和Apache Commons Codec对PDF文件进行Base64编码和解码。

但是首先,让我们快速了解一下Base64的基础知识。

2. Base64的基础

通过有线发送数据时,我们需要以二进制格式发送数据。但是,如果我们仅发送0和1,则不同的传输层协议可能会不同地解释它们,并且我们的数据可能会在飞行中损坏。

因此,为了在传输二进制数据时具有可移植性和通用标准,图片中使用了Base64。

由于发送者和接收者都理解并同意使用该标准,因此大大降低了我们的数据丢失或被误解的可能性。

现在,让我们看看将其应用于PDF的几种方法。

3.使用Java 8进行转换

从Java 8开始,我们有一个实用程序java.util.Base64,它为Base64编码方案提供编码器和解码器。它支持RFC 4648和RFC 2045中指定的基本,URL安全和MIME类型。

3.1。编码方式

要将PDF转换为Base64,我们首先需要以字节为单位获取它,并将其通过java.util.Base64.Encoder的encoding方法传递:

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

在这里,IN_FILE是输入PDF的路径。

3.2。流编码

对于较大的文件或内存有限的系统,使用流而不是读取内存中的所有数据来执行编码会更加有效。让我们看看如何完成此任务:

1
2
3
4
5
6
7
8
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:

1
2
3
4
5
6
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中添加一个依赖项:

1
2
3
4
5
<dependency>
    <groupId>commons-codec</groupId>
    commons-codec</artifactId>
    <version>1.14</version>
</dependency>

上面的最新版本可以在Maven Central中找到。

4.2。编码方式

步骤与Java 8相同,除了这次,我们将原始字节传递给org.apache.commons.codec.binary.Base64class的encodeBase64方法:

1
2
byte[] inFileBytes = Files.readAllBytes(Paths.get(IN_FILE));
byte[] encoded = org.apache.commons.codec.binary.Base64.encodeBase64(inFileBytes);

4.3。流编码

该库不支持流编码。

4.4。解码

同样,我们只需要调用encodeBase64方法并将结果写入文件即可:

1
2
3
4
5
6
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测试来测试编码和解码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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文件,并查看其内容与我们输入的文件相同。

    六,结论

    在本快速教程中,我们了解了有关Java的Base64实用程序的更多信息。

    我们还看到了使用Java 8和Apache Commons Codec将PDF转换为Base64和从Base64转换PDF的代码示例。有趣的是,JDK的实现比Apache的实现快得多。

    与往常一样,源代码可以在GitHub上获得。