如何在 Java 中将常见文档转换为 PNG 图像数组

简介: 如何在 Java 中将常见文档转换为 PNG 图像数组

如何使用 Java 中的 Web API 轻松地将各种常见文档格式转换为 PNG 图像数组。在进入本文的演示部分之前,我们将首先回顾一下将文档转换为不太灵活的格式背后的常见逻辑,并最终讨论 PNG 格式相对于其他常见格式(如 PDF 或 JPG)提供的优势。

为什么要将文档转换为不灵活的格式?

       针对文档编辑和操作优化的文件格式通常不会针对其他方案的效率进行优化。有一长串论据支持将此类文档转换为静态格式(如 PDF),用于文档编辑和操作以外的任何场景。

       内容安全是其中最有力的论据之一。设计为在编辑应用程序中打开和操作的文档格式在设计上保留了高度可访问和易于互换的属性,这意味着未经请求的第三方(即未知的陌生人)可以随意更改这些应用程序中的文档。其中技术娴熟的人甚至可以毫不费力地对常见的文档格式进行编程/自动更改。例如,不乏旨在解压缩和操作 XLSX、DOCX 或 PPTX 等开放式办公室 XML (OpenXML) 文件的 API 和库(我在之前的文章中已经写过很多)。以原始格式公开共享或显示 Office 文档会带来麻烦;在现实世界中,我们几乎看不到这样做是有原因的。

       当然,这不仅仅是关于安全性。复杂的 OpenXML 文件和其他类似的分层文档格式旨在将大量数据保留在一个地方(包括文本、链接、元数据和多媒体),这使得存储、传输或流式传输这些文件成为任何规模的负担。例如,如果我们要与网络中的利益相关者共享一系列最终确定的 Excel XLSX 报告(包括图形和数字),我们将在此过程中占用大量带宽,因此我们的传输速度会受到影响。如果我们将所有这些文件存储在一起而不压缩它们,我们将消耗不成比例的大量文件存储分配,随着时间的推移,这可能会证明成本很高——尤其是对于现代即用即付的云存储模型。同样,如果我们编写应用程序以将 Excel 文件管道传输到 Web 应用程序门户上基于 Web 的文件查看器(即,使用 iframe 标记),我们可能会大大减慢该页面的加载速度。

在现实世界中,这些挑战的结果是,大多数文档在进入存储、传输或流式处理状态之前,通常会转换为安全、静态且相对简单的格式。在大多数情况下,该格式为 PDF。

PDF的优缺点

       PDF 是大多数常见内容形式(尤其是 OpenXML 文档)事实上的发布格式,这是有充分理由的。它可以在任何 Web 浏览器上访问,并提供各种安全优势,同时与无数文件渲染和处理应用程序保持兼容。它可以结构为多媒体矢量文件或光栅(位图)文件,确保可以适应各种独特的内容类型,以适应同样广泛的显示方案。

       但是,PDF本身并不能立即解决的问题是压缩。PDF 仍然是相对复杂的文件,通常在其文件结构中存储布局、字体、矢量图形、文档历史记录和文档元数据。此外,光栅 PDF 以位图格式显示像素,默认情况下,该格式包含比其他图像类型更高的颜色深度范围(例如 24 位或 32 位)。这使得光栅 PDF 成为高质量静态文档内容显示和文档打印的绝佳选择,但对于轻量级存储和传输来说却不太有利。

选择PNG而不是JPG作为PDF替代品

       当 PDF 文件结构的特性和功能超出我们的需求时,我们可以将注意力转向更简单、重量更轻的格式选项。在这些选项中,有两种最常见的图像格式:PNG 和 JPG。

       这两种格式都提供了显着的压缩功能,JPG 比 PNG 在更大程度上做到了这一点。然而,对于JPG,这种压缩的成本要高得多。JPG 压缩算法试图通过删除一些我们通常不容易注意到的图像细节来减小文件大小,使用颜色子采样(即以低于亮度信息的分辨率存储颜色信息)和量化(即降低图像中颜色和亮度值的整体精度)等技术。随着时间的推移,JPG压缩变得越来越明显,这使得将详细文档转换为JPG屏幕截图成为一项冒险的工作。另一方面,PNG 牺牲了稍大的最终文件大小,以获得不会丢弃与图像质量相关的数据的压缩算法。PNG 压缩采用预测编码和像素值过滤等概念来优化图像数据,并使用 Deflate Compression 来识别图像数据中的重复模式,并用较短的代码替换这些模式。生成的 PNG 文件可能比 JPG 略大,但它们的质量可以保证随着时间的推移保持一致,使其成为存储和显示高质量文档内容的绝佳选择。

示范

       在本文的演示部分,我们将逐步学习如何调用免费 API,该 API 可自动检测各种输入文档类型(包括所有主要的 Office 文档格式、PDF 和 100 多种不同的图像格式)并将其转换为 PNG 图像数组。在实践中,它实际上是一种自动屏幕截图解决方案,我们可以直接将其插入到我们的 Java Web 应用程序中。它通过将 PNG 文件内容作为临时 URL 数组(每个 PNG 图像一个)返回来优化转换后的下载过程,随后可以下载这些 URL 并将其转换为文件字节。要使用此 API,我们只需要一个免费的 API 密钥,这将使我们每月使用 800 次 API 调用的限制。

要开始构建我们的 API 调用,我们将首先安装 Maven SDK(jitpack 用于动态编译库)。让我们在 pom.xml 中添加对存储库的引用。

XML格式

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

之后,让我们在 pom.xml 中添加对依赖项的引用:

XML格式

<dependencies>
<dependency>
    <groupId>com.github.Cloudmersive</groupId>
    <artifactId>Cloudmersive.APIClient.Java</artifactId>
    <version>v4.25</version>
</dependency>
</dependencies>

在下一步中,我们会将以下导入添加到文件顶部:

// Import classes:
//import com.cloudmersive.client.invoker.ApiClient;
//import com.cloudmersive.client.invoker.ApiException;
//import com.cloudmersive.client.invoker.Configuration;
//import com.cloudmersive.client.invoker.auth.*;
//import com.cloudmersive.client.ConvertDocumentApi;

之后,我们将添加配置代码段来捕获我们的 API 密钥:

ApiClient defaultClient = Configuration.getDefaultApiClient();
// Configure API key authorization: Apikey
ApiKeyAuth Apikey = (ApiKeyAuth) defaultClient.getAuthentication("Apikey");
Apikey.setApiKey("YOUR API KEY");
// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null)
//Apikey.setApiKeyPrefix("Token");

最后,我们将添加以下代码片段以创建 API 实例并调用该函数进行转换:

ConvertDocumentApi apiInstance = new ConvertDocumentApi();
File inputFile = new File("/path/to/inputfile"); // File | Input file to perform the operation on.
try {
    AutodetectToPngResult result = apiInstance.convertDocumentAutodetectToPngArray(inputFile);
    System.out.println(result);
} catch (ApiException e) {
    System.err.println("Exception when calling ConvertDocumentApi#convertDocumentAutodetectToPngArray");
    e.printStackTrace();
}

我们可以通过几种不同的方式处理从临时 URL 到 PNG 文件字节的转换。我们可以使用以下代码进行辅助 API 调用(来自同一库并遵循与以前相同的基本结构)来处理该问题:

// Import classes:
//import com.cloudmersive.client.invoker.ApiClient;
//import com.cloudmersive.client.invoker.ApiException;
//import com.cloudmersive.client.invoker.Configuration;
//import com.cloudmersive.client.invoker.auth.*;
//import com.cloudmersive.client.EditDocumentApi;

ApiClient defaultClient = Configuration.getDefaultApiClient();

// Configure API key authorization: Apikey
ApiKeyAuth Apikey = (ApiKeyAuth) defaultClient.getAuthentication("Apikey");
Apikey.setApiKey("YOUR API KEY");
// Uncomment the following line to set a prefix for the API key, e.g. "Token" (defaults to null)
//Apikey.setApiKeyPrefix("Token");

EditDocumentApi apiInstance = new EditDocumentApi();
FinishEditingRequest reqConfig = new FinishEditingRequest(); // FinishEditingRequest | Cloudmersive Document URL to complete editing on
try {
    byte[] result = apiInstance.editDocumentFinishEditing(reqConfig);
    System.out.println(result);
} catch (ApiException e) {
    System.err.println("Exception when calling EditDocumentApi#editDocumentFinishEditing");
    e.printStackTrace();
}

或者,我们可以使用 from 类( 的基本部分)。这允许我们从文件 URL 创建一个 URL 对象,从 URL 读取和写入文件字节,并将字节流转换为可下载的文件内容。java.net.HttpURLConnectionjava.netJDK

       无论哪种情况,我们只需要将文件字节写入新的 PNG 文档,我们就可以轻松地在转换工作流程下游的任何位置存储、传输或流式传输该内容。

以静态图像格式存储、传输和流式传输文档的一些原因,并了解了 PNG 如何以 PDF 和 JPG 无法做到的方式提供轻量级无损压缩。


目录
相关文章
|
23天前
|
存储 缓存 算法
Java 数组
【10月更文挑战第19天】Java 数组是一种非常实用的数据结构,它为我们提供了一种简单而有效的方式来存储和管理数据。通过合理地使用数组,我们能够提高程序的运行效率和代码的可读性。更加深入地了解和掌握 Java 数组的特性和应用,为我们的编程之旅增添更多的精彩。
31 4
|
23天前
|
存储 缓存 算法
提高 Java 数组性能的方法
【10月更文挑战第19天】深入探讨了提高 Java 数组性能的多种方法。通过合理运用这些策略,我们可以在处理数组时获得更好的性能表现,提升程序的运行效率。
19 2
|
29天前
|
Java Apache Maven
Java将word文档转换成pdf文件的方法?
【10月更文挑战第13天】Java将word文档转换成pdf文件的方法?
135 1
|
1月前
|
存储 Java
Java“(array) <X> Not Initialized” (数组未初始化)错误解决
在Java中,遇到“(array) &lt;X&gt; Not Initialized”(数组未初始化)错误时,表示数组变量已被声明但尚未初始化。解决方法是在使用数组之前,通过指定数组的大小和类型来初始化数组,例如:`int[] arr = new int[5];` 或 `String[] strArr = new String[10];`。
|
1月前
|
存储 Java
什么是带有示例的 Java 中的交错数组?
什么是带有示例的 Java 中的交错数组?
43 9
|
1月前
|
Java
Java数组动态扩容和动态缩减
Java数组动态扩容和动态缩减
22 3
|
1月前
|
存储 算法 Java
Java一分钟之-数组的创建与遍历
数组作为Java中存储和操作一组相同类型数据的基本结构,其创建和遍历是编程基础中的基础。通过不同的创建方式,可以根据实际需求灵活地初始化数组。而选择合适的遍历方法,则可以提高代码的可读性和效率。掌握这些基本技能,对于深入学习Java乃至其他编程语言的数据结构和算法都是至关重要的。
25 6
|
1月前
|
存储 Java 程序员
【一步一步了解Java系列】:何为数组,何为引用类型
【一步一步了解Java系列】:何为数组,何为引用类型
23 1
|
1月前
|
存储 安全 Java
Java数组(Arrays)详解
Java 中的数组是一种用于存储固定数量同类型数据的高效数据结构,支持连续内存存储和随机访问。数组可以声明并初始化,通过索引访问和修改元素,获取长度,使用循环遍历,支持多维形式,并可通过 `Arrays` 类的方法进行复制和排序。数组具有固定大小和类型安全的特点,但需注意越界等问题。灵活运用数组能显著提升编程效率。
|
1月前
|
存储 算法 Java
带你学习java的数组军队列
带你学习java的数组军队列
34 0