共计 8030 个字符,预计需要花费 21 分钟才能阅读完成。
在理论的开发过程中,可能会遇到以下的一些场景:
- 一个全副为竖版的 PDF 文件,当初须要将其全副转换为横版 PDF 文件;
- 一个全副为竖版的 PDF 文件,当初须要将指定页转换为横版 PDF 文件;
- 一个 PDF 文件中既有横板也有竖版,当初须要将所有横版转换为竖版;
- 一个 PDF 文件中既有横板也有竖版,当初须要将所有竖版转换为横版;
这些需要都能够通过应用 itextpdf
开源库来实现,上面来通过代码进行演示。
须要阐明的是,这里的转换只是 PDF 版式的旋转,并非是页面内容的旋转,如果须要在旋转版式的时候,同时旋转页面上的文字,那么上面的办法可能不太实用了。
1、引入依赖
目前 itextpdf
最新版本为 5.5.13.3
,能够在 https://search.maven.org/ 网站进行搜寻。
<dependency> | |
<groupId>com.itextpdf</groupId> | |
<artifactId>itextpdf</artifactId> | |
<version>5.5.13.3</version> | |
</dependency> |
2、代码实现
不论是横版 PDF 转竖版 PDF,还是竖版 PDF 转横板 PDF,其实都是旋转问题,比方将一个横版 PDF 顺时针或者逆时针旋转 90,失去的就是一个竖版的 PDF,而将一个竖版 PDF 顺时针或者逆时针旋转 90,失去的就是一个横板的 PDF。
package com.magic.itextpdf; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.util.List; | |
import com.itextpdf.text.Document; | |
import com.itextpdf.text.DocumentException; | |
import com.itextpdf.text.pdf.PdfCopy; | |
import com.itextpdf.text.pdf.PdfDictionary; | |
import com.itextpdf.text.pdf.PdfName; | |
import com.itextpdf.text.pdf.PdfNumber; | |
import com.itextpdf.text.pdf.PdfReader; | |
import com.itextpdf.text.pdf.PdfSmartCopy; | |
/** | |
* PDF 工具类 | |
*/ | |
public class PdfUtils { | |
/** | |
* 旋转 PDF 文件 | |
* @param sourceFile 源 PDF 文件门路 | |
* @param targetFile 指标 PDF 文件门路 | |
* @param angle 旋转角度 | |
*/ | |
public static void rotate(String sourceFile, String targetFile, int angle) { | |
PdfReader reader = null; | |
Document document = null; | |
FileOutputStream outputStream = null; | |
try { | |
// 读取源文件 | |
reader = new PdfReader(sourceFile); | |
// 创立新的文档 | |
document = new Document(); | |
// 创立指标 PDF 文件 | |
outputStream = new FileOutputStream(targetFile); | |
PdfCopy pdfCopy = new PdfSmartCopy(document, outputStream); | |
// 获取源文件的页数 | |
int pages = reader.getNumberOfPages(); | |
document.open(); | |
PdfDictionary pdfDictionary; | |
// 留神此处的页码是从 1 开始 | |
for (int page = 1; page <= pages; page++) {pdfDictionary = reader.getPageN(page); | |
pdfDictionary.put(PdfName.ROTATE, new PdfNumber(angle)); | |
pdfCopy.addPage(pdfCopy.getImportedPage(reader, page)); | |
} | |
} catch (IOException | DocumentException e) {e.printStackTrace(); | |
} finally {if (reader != null) {reader.close(); | |
} | |
if (document != null) {document.close(); | |
} | |
if (outputStream != null) { | |
try {outputStream.flush(); | |
outputStream.close();} catch (IOException e) {e.printStackTrace(); | |
} | |
} | |
} | |
} | |
} |
这里的旋转角度 angle
必须是 90 的倍数,如果是其余的角度,则是有效的。有了旋转的办法后,咱们能够再定义一些根底办法,比方 顺时针旋转(右旋转)、逆时针旋转(左旋转)和垂直翻转,这样应用起来会更加不便。
(1)顺时针旋转(右旋转 90)
/** | |
* 右旋转 PDF 文件 90 度 | |
* @param sourceFile 源 PDF 文件门路 | |
* @param targetFile 指标 PDF 文件门路 | |
*/ | |
public static void rightRotate(String sourceFile, String targetFile) {rotate(sourceFile, targetFile, -90); | |
} |
(2)逆时针旋转(左旋转 90)
/** | |
* 左旋转 PDF 文件 90 度 | |
* @param sourceFile 源 PDF 文件门路 | |
* @param targetFile 指标 PDF 文件门路 | |
*/ | |
public static void leftRotate(String sourceFile, String targetFile) {rotate(sourceFile, targetFile, 90); | |
} |
(3)垂直(旋转 180)
/** | |
* 翻转 PDF 文件 | |
* @param sourceFile 源 PDF 文件门路 | |
* @param targetFile 指标 PDF 文件门路 | |
*/ | |
public static void filp(String sourceFile, String targetFile) {rotate(sourceFile, targetFile, 180); | |
} |
在某些固定的场景下,可能旋转就是特指逆时针旋转,那么这个时候,咱们还能够重载 rotate()
办法,默认应用 leftRotate()
办法,如下:
/** | |
* 旋转 PDF 文件 | |
* @param sourceFile 源 PDF 文件门路 | |
* @param targetFile 指标 PDF 文件门路 | |
*/ | |
public static void rotate(String sourceFile, String targetFile) {leftRotate(sourceFile, targetFile); | |
} |
3、指定页面旋转
下面的实现是将所有的 PDF 文件都旋转,然而有的时候,可能只想旋转指定的页码,而其余的放弃不变,能够采纳重载 rotate()
办法来实现指定页码旋转。
/** | |
* 旋转 PDF 文件 | |
* @param sourceFile 源 PDF 文件门路 | |
* @param targetFile 指标 PDF 文件门路 | |
* @param angle 旋转角度 | |
* @param rotatedPageNums 须要旋转的页码 | |
*/ | |
public static void rotate(String sourceFile, String targetFile, int angle, List<Integer> rotatedPageNums) { | |
PdfReader reader = null; | |
Document document = null; | |
FileOutputStream outputStream = null; | |
try { | |
// 读取源文件 | |
reader = new PdfReader(sourceFile); | |
// 创立新的文档 | |
document = new Document(); | |
// 创立指标 PDF 文件 | |
outputStream = new FileOutputStream(targetFile); | |
PdfCopy pdfCopy = new PdfSmartCopy(document, outputStream); | |
// 获取源文件的页数 | |
int pages = reader.getNumberOfPages(); | |
document.open(); | |
PdfDictionary pdfDictionary; | |
// 留神此处的页码是从 1 开始 | |
for (int page = 1; page <= pages; page++) {pdfDictionary = reader.getPageN(page); | |
if (null == rotatedPageNums || rotatedPageNums.isEmpty()) {pdfDictionary.put(PdfName.ROTATE, new PdfNumber(angle)); | |
} else if (rotatedPageNums.contains(page)) {pdfDictionary.put(PdfName.ROTATE, new PdfNumber(angle)); | |
} | |
pdfCopy.addPage(pdfCopy.getImportedPage(reader, page)); | |
} | |
} catch (IOException | DocumentException e) {e.printStackTrace(); | |
} finally {if (reader != null) {reader.close(); | |
} | |
if (document != null) {document.close(); | |
} | |
if (outputStream != null) { | |
try {outputStream.flush(); | |
outputStream.close();} catch (IOException e) {e.printStackTrace(); | |
} | |
} | |
} | |
} |
这个办法多了一个参数 List<Integer> rotatedPageNums
,传递的是须要旋转的页码,比如说须要旋转 1、3、5 页,那么能够这样调用:
PdfUtils.rotate("D:\\Test\\test.pdf", "D:\\Test\\test_out.pdf", 90, Arrays.asList(1, 3, 5));
如果间断旋转某些页面,比方从 10-60,如果应用下面的办法调用的话,那么参数就比拟多了,这个时候,又能够重载一个办法,来依据起始页码和完结页码实现旋转,具体代码如下:
/** | |
* 旋转 PDF 文件 | |
* @param sourceFile 源 PDF 文件门路 | |
* @param targetFile 指标 PDF 文件门路 | |
* @param angle 旋转角度 | |
* @param fromPageNum 起始页码 | |
* @param toPageNum 完结页码 | |
*/ | |
public static void rotate(String sourceFile, String targetFile, int angle, int fromPageNum, int toPageNum) { | |
PdfReader reader = null; | |
Document document = null; | |
FileOutputStream outputStream = null; | |
try { | |
// 读取源文件 | |
reader = new PdfReader(sourceFile); | |
// 创立新的文档 | |
document = new Document(); | |
// 创立指标 PDF 文件 | |
outputStream = new FileOutputStream(targetFile); | |
PdfCopy pdfCopy = new PdfSmartCopy(document, outputStream); | |
// 获取源文件的页数 | |
int pages = reader.getNumberOfPages(); | |
document.open(); | |
PdfDictionary pdfDictionary; | |
// 留神此处的页码是从 1 开始 | |
for (int page = 1; page <= pages; page++) {pdfDictionary = reader.getPageN(page); | |
// 如果页面是在起始页码和完结页码之间的,则进行旋转 | |
if (page >= fromPageNum && page <= toPageNum) {pdfDictionary.put(PdfName.ROTATE, new PdfNumber(angle)); | |
} | |
pdfCopy.addPage(pdfCopy.getImportedPage(reader, page)); | |
} | |
} catch (IOException | DocumentException e) {e.printStackTrace(); | |
} finally {if (reader != null) {reader.close(); | |
} | |
if (document != null) {document.close(); | |
} | |
if (outputStream != null) { | |
try {outputStream.flush(); | |
outputStream.close();} catch (IOException e) {e.printStackTrace(); | |
} | |
} | |
} | |
} |
此时就能够依据起始完结页码来旋转了,如下:
PdfUtils.rotate("D:\\Test\\test.pdf", "D:\\Test\\test_out.pdf", 90, 10, 60);
4、旋转所有横版
如果一个 PDF 文件中既有横版,又有竖版,这个时候心愿把所有的横版都转换为竖版,下面已有的办法是满足不了的,能够定义新的办法,如下:
/** | |
* 旋转 PDF 文件中的所有横版 | |
* @param sourceFile 源 PDF 文件门路 | |
* @param targetFile 指标 PDF 文件门路 | |
* @param angle 旋转角度 | |
*/ | |
public static void rotateHorizontal(String sourceFile, String targetFile, int angle) { | |
PdfReader reader = null; | |
Document document = null; | |
FileOutputStream outputStream = null; | |
try { | |
// 读取源文件 | |
reader = new PdfReader(sourceFile); | |
// 创立新的文档 | |
document = new Document(); | |
// 创立指标 PDF 文件 | |
outputStream = new FileOutputStream(targetFile); | |
PdfCopy pdfCopy = new PdfSmartCopy(document, outputStream); | |
// 获取源文件的页数 | |
int pages = reader.getNumberOfPages(); | |
document.open(); | |
PdfDictionary pdfDictionary; | |
// 留神此处的页码是从 1 开始 | |
for (int page = 1; page <= pages; page++) {pdfDictionary = reader.getPageN(page); | |
// 依据页面的宽度 | |
float pageWidth = reader.getPageSize(page).getWidth(); | |
if (pageWidth > 600F) {pdfDictionary.put(PdfName.ROTATE, new PdfNumber(angle)); | |
} | |
pdfCopy.addPage(pdfCopy.getImportedPage(reader, page)); | |
} | |
} catch (IOException | DocumentException e) {e.printStackTrace(); | |
} finally {if (reader != null) {reader.close(); | |
} | |
if (document != null) {document.close(); | |
} | |
if (outputStream != null) { | |
try {outputStream.flush(); | |
outputStream.close();} catch (IOException e) {e.printStackTrace(); | |
} | |
} | |
} | |
} |
旋转所有的横版,是依据页面的宽度进行,横版的宽度比竖版的宽,而对于横版 A4 版面 PDF 文件,其宽高别离为 841.9 和 595.3。
5、旋转所有竖版
下面实现了旋转所有的横版,同理,可能也会遇到须要旋转所有的竖版的需要,代码如下:
/** | |
* 旋转 PDF 文件中的所有竖版 | |
* @param sourceFile 源 PDF 文件门路 | |
* @param targetFile 指标 PDF 文件门路 | |
* @param angle 旋转角度 | |
*/ | |
public static void rotateVertical(String sourceFile, String targetFile, int angle) { | |
PdfReader reader = null; | |
Document document = null; | |
FileOutputStream outputStream = null; | |
try { | |
// 读取源文件 | |
reader = new PdfReader(sourceFile); | |
// 创立新的文档 | |
document = new Document(); | |
// 创立指标 PDF 文件 | |
outputStream = new FileOutputStream(targetFile); | |
PdfCopy pdfCopy = new PdfSmartCopy(document, outputStream); | |
// 获取源文件的页数 | |
int pages = reader.getNumberOfPages(); | |
document.open(); | |
PdfDictionary pdfDictionary; | |
// 留神此处的页码是从 1 开始 | |
for (int page = 1; page <= pages; page++) {pdfDictionary = reader.getPageN(page); | |
// 依据页面的高度 | |
float pageHeight = reader.getPageSize(page).getHeight(); | |
if (pageHeight > 600F) {pdfDictionary.put(PdfName.ROTATE, new PdfNumber(angle)); | |
} | |
pdfCopy.addPage(pdfCopy.getImportedPage(reader, page)); | |
} | |
} catch (IOException | DocumentException e) {e.printStackTrace(); | |
} finally {if (reader != null) {reader.close(); | |
} | |
if (document != null) {document.close(); | |
} | |
if (outputStream != null) { | |
try {outputStream.flush(); | |
outputStream.close();} catch (IOException e) {e.printStackTrace(); | |
} | |
} | |
} | |
} |
如果一个 PDF 文件同时存在 A4 横版和 A4 竖版,那么竖版的高度比横版的高,并且竖版的高度值为横版的宽度,这个时候横竖版的宽高别离如下:
- 横版:841.9 x 595.3
- 竖版:595.3 x 841.9
6、测试验证
当初应用下面的旋转办法把一个 PDF 中的第 2 页转换为竖版,测试代码如下:
package com.magic.itextpdf; | |
import java.util.Collections; | |
public class Test {public static void main(String[] args) {PdfUtils.rotate("D:\\Test\\test.pdf", "D:\\Test\\test_2.pdf", 90, 2, 2); | |
} | |
} |
原始 PDF 和转换后的 PDF 比照如下: