在理论的开发过程中,可能会遇到以下的一些场景:

  • 一个全副为竖版的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比照如下: