生成PDF文件

使用itextpdf的工具包来生成PDF数据流,pdfbox将pdf转成图片。

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.10</version>
</dependency>
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-asian</artifactId>
    <version>5.2.0</version>
</dependency>

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.20</version>
</dependency>

应需求开发pdf生成的代码,对pdf流有两种处理方式,1、直接返回文件;2、将PDF转成图片。

​
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Component
public class PDFUtil {


    private static Logger logger = LoggerFactory.getLogger(PDFUtil.class);

    // 定义全局的字体静态变量
    private static com.itextpdf.text.Font titleFont;
    private static com.itextpdf.text.Font titleFont1;
    private static com.itextpdf.text.Font titleFont2;
    private static com.itextpdf.text.Font textFont;
    private static com.itextpdf.text.Font textFont2;
    private static com.itextpdf.text.Font textFont3;
    // 最大宽度
    private static final int maxWidth = 450;

    // 静态代码块(设置PDF里面会用到的字体的样式)
    static {
        try {
            // 不同字体(这里定义为同一种字体:包含不同字号、不同style)
            BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            titleFont = new com.itextpdf.text.Font(bfChinese, 15, com.itextpdf.text.Font.BOLD);
            titleFont1 = new com.itextpdf.text.Font(bfChinese, 12, com.itextpdf.text.Font.BOLD);
            titleFont2 = new com.itextpdf.text.Font(bfChinese, 12, com.itextpdf.text.Font.NORMAL);
            textFont = new com.itextpdf.text.Font(bfChinese, 12, com.itextpdf.text.Font.NORMAL);
            textFont2 = new com.itextpdf.text.Font(bfChinese, 9, com.itextpdf.text.Font.NORMAL);
            textFont3 = new com.itextpdf.text.Font(bfChinese, 10, com.itextpdf.text.Font.NORMAL, com.itextpdf.text.BaseColor.DARK_GRAY);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("字体设置失败:{}", e);
        }
    }
// 生成PDF文件
public static ByteArrayOutputStream generatePDF(GeneratePDFRequest request) {
    try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
        // 1.新建document对象
        Document document = new Document(PageSize.A4, 90, 90, 60, 70);// 建立一个Document对象
        // 2.建立一个书写器(Writer)与document对象关联
        PdfWriter writer = PdfWriter.getInstance(document, out);
        document.open();
        // 段落
        String titleText = "第一行标题";
        Paragraph title = new Paragraph(titleText, titleFont);
        title.setAlignment(1); //设置文字居中 0靠左   1,居中     2,靠右
        title.setSpacingAfter(10f); //设置段落上空白
        document.add(title);
        String titleText2 = "第二行小标题";
        Paragraph title2 = new Paragraph(titleText2, titleFont);
        title2.setAlignment(1); //设置文字居中 0靠左   1,居中     2,靠右
        title2.setSpacingAfter(10f); //设置段落上空白
        document.add(title2);
         // 表格20,40等数字表示表格单元宽度,一共5列,pdf的添加方式就是addCell,拼接单元格到pdf上面
        PdfPTable table = createTable(new float[]{20, 40, 50, 40, 50});
        table.addCell(createCellRows("第一行合并第二行", titleFont1, Element.ALIGN_CENTER, 2));
        table.addCell(createCell("第一行第2列", textFont, Element.ALIGN_CENTER));
        table.addCell(createCellCols(request.getField1(), textFont3,         Element.ALIGN_CENTER, 3));//合并第一行的3-5列
        table.addCell(createCell("第二行第2列", textFont, Element.ALIGN_CENTER));
        table.addCell(createCell(request.getField2(), textFont3, Element.ALIGN_CENTER));
        table.addCell(createCell("第二行第4列", textFont, Element.ALIGN_CENTER));
        table.addCell(createCell(request.getField3(), textFont3, Element.ALIGN_CENTER));
    //给复选框打勾(类似签名的方式) 
    String isSign = request.getIsSign();
    if ("1".equals(isSign)) {
    //如果需要签名,那么报账一致需要勾选
        RadioCheckField bt = new RadioCheckField(writer, new Rectangle(90, 605, 100, 615),
            "check1", "No");//90(100)表示图片左(右)下角离PDF文件左下角的横向距离,605(615)表示图片左(右)上角离PDF文件左下角的纵向距离
        bt.setCheckType(RadioCheckField.TYPE_CHECK);
        bt.setBorderWidth(BaseField.BORDER_WIDTH_THIN);
        bt.setBorderColor(BaseColor.BLACK);
        bt.setBackgroundColor(BaseColor.WHITE);
        bt.setChecked(true);
        PdfFormField ck = bt.getCheckField();
        writer.addAnnotation(ck);
        PdfPCell cell = createCell("", textFont, Element.ALIGN_CENTER);
        table.addCell(cell);
        table.addCell(createCell("数据一致", titleFont1, Element.ALIGN_CENTER));
        table.addCell(createCellCols("复选框已打勾",
            textFont, Element.ALIGN_LEFT, 3));
    } else {
        table.addCell(createCell("□", textFont, Element.ALIGN_CENTER));
        table.addCell(createCell("数据不一致", titleFont1, Element.ALIGN_CENTER));
        table.addCell(createCellCols("复选框未打勾",
            textFont, Element.ALIGN_LEFT, 3));
    }
        document.add(table);
        Paragraph title4 = new Paragraph("备注信息:1。", textFont2);
        title4.setAlignment(0);
        document.add(title4);

        Chunk textAsChunk = new Chunk("备注信息2", textFont2);
        textAsChunk.setBackground(BaseColor.YELLOW);//加背景色
        Paragraph title5 = new Paragraph(textAsChunk);
        title5.setAlignment(0);
        document.add(title5);
        // 5.关闭文档
        document.close();
        return out;
} catch (Exception e) {
        e.printStackTrace();
        logger.error("生成异常报告失败:{}", e);
        throw ExceptionFactory.service("Fl00005");
    }
}

​  /**
     * 创建指定列宽、列数的表格
     */
    private static PdfPTable createTable(float[] widths) {
        PdfPTable table = new PdfPTable(widths);
        try {
            table.setTotalWidth(maxWidth);
            table.setLockedWidth(true);
            table.setHorizontalAlignment(Element.ALIGN_CENTER);
            table.getDefaultCell().setBorder(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return table;
    }

    /**
     * 创建单元格(指定字体、水平..)
     */
    private static PdfPCell createCell(String value, com.itextpdf.text.Font font, int align) {
        PdfPCell cell = new PdfPCell();
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(align);
        cell.setPhrase(new Phrase(value, font));
        return cell;
    }

    /**
     * 创建单元格列合并(指定字体、水平居..、单元格跨x列合并)
     */
    private static PdfPCell createCellCols(String value, com.itextpdf.text.Font font, int align, int colspan) {
        PdfPCell cell = new PdfPCell();
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(align);
        cell.setColspan(colspan);
        cell.setPhrase(new Phrase(value, font));
        return cell;
    }

    /**
     * 创建单元格行合并(指定字体、水平居..、单元格跨x列合并)
     */
    private static PdfPCell createCellRows(String value, com.itextpdf.text.Font font, int align, int rowspan) {
        PdfPCell cell = new PdfPCell();
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(align);
        cell.setRowspan(rowspan);
        cell.setPhrase(new Phrase(value, font));
        return cell;
    }

    /**
     * dpi越大转换后越清晰,相对转换速度越慢
     */
    private static final Integer DPI = 100;

    /**
     * 转换后的图片类型
     */
    private static final String IMG_TYPE = "png";


    /**
     * PDF转图片
     *
     * @param fileContent PDF文件的二进制流
     * @return 图片文件的二进制流
     */
    public static byte[] pdfToImage(byte[] fileContent) throws IOException {
        List<byte[]> result = new ArrayList<>();
        try (PDDocument document = PDDocument.load(fileContent)) {
            PDFRenderer renderer = new PDFRenderer(document);
            for (int i = 0; i < document.getNumberOfPages(); ++i) {
                BufferedImage bufferedImage = renderer.renderImageWithDPI(i, DPI);
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                ImageIO.write(bufferedImage, IMG_TYPE, out);
                result.add(out.toByteArray());
            }
        }
        return result.get(0);
    }

}

调用返回的方法

     ByteArrayOutputStream bos = PDFUtil.generatePDF(request);

        try {
            OutputStream os = httpServletResponse.getOutputStream();
            if ("1".equals(request.getIsSign())) {
                //如果是选择的,直接返回图片
                byte[] bs = PDFUtil.pdfToImage2(bos.toByteArray());
                os.write(bs);
                os.close();
            } else {
                //如果未选中,那么返回pdf文件
                os.write(bos.toByteArray());
                os.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

以上是生成PDF工具方法以及调用方法,记录下来方便自己和他人查看使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值