天天看点

java实现PDF报表生成通用工具类

java实现PDF报表生成通用工具类,可实现添加水印,提供前端下载方法。

首先在maven中引入需用到的jar包:

<!--引入PDF处理-->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
           

PdfUtil工具类:

import com.itextpdf.text.*;
import com.itextpdf.text.Font;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import org.apache.commons.io.IOUtils;

import javax.servlet.http.HttpServletResponse;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.lang.reflect.Field;
import java.util.List;

/**
 * @author :debruyne
 * @date :Created in 2019/12/10 15:18
 * @description: PDF文件工具类
 * @modified By:
 * @version: $
 */
public class PdfUtil {
    /**
     * @param objectList 报表内容list
     * @param copyPath 生成文件路径(至文件名)
     * @param title  报表标题
     * @param columnHeaders 报表 列标题数组
     * @param <T> 内容类型
     * @throws IllegalAccessException
     */
    public static <T> void generatePdfFile(List<T> objectList, String copyPath, String title, String[] columnHeaders) throws IllegalAccessException {
        try {
            // 新建文件
            Document document = new Document();
            //建立一个书写器(Writer)与document对象关联,并把文档写入到磁盘中
            PdfWriter.getInstance(document, new FileOutputStream(copyPath));
            document.open();
            // 中文字体
            BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
            // 标题字体
            Font titleChinese = new Font(bfChinese, 16, Font.BOLD);
            // 内容小标题字体
            Font contenttitleChinese = new Font(bfChinese, 11, Font.BOLD);
            //设置标题
            Paragraph par = new Paragraph(title, titleChinese);
            par.setAlignment(Element.ALIGN_CENTER);
            //文档中加入标题
            document.add(par);
            //文档中加入空行
            Paragraph blankRow51 = new Paragraph(18f, " ", contenttitleChinese);
            document.add(blankRow51);
            //设置表格的列数
            int col = columnHeaders.length;
            //新建一个表格
            PdfPTable table = new PdfPTable(col);
            //设置表格占PDF文档100%宽度
            table.setWidthPercentage(100);
            //设置每列表格宽度
            int[] widths=new int[columnHeaders.length];
            int wight=100/columnHeaders.length;
            for (int i = 0; i < widths.length; i++) {
                widths[i]=wight;
            }
            table.setWidths(widths);
            //设置表格标题样式
            BaseColor lightGrey01 = new BaseColor(0xCC,0xCC,0xCC);
            for (int i = 0; i < columnHeaders.length; i++) {
                PdfPCell cell = toPdfPCell(columnHeaders[i],Element.ALIGN_CENTER);
                cell.setBackgroundColor(lightGrey01);
                table.addCell(cell);
            }
            //表格赋值啊,这里使用反射获取对象属性
            if (objectList.size()>0){
                for (T obj : objectList) {
                    Field[] fields= obj.getClass().getDeclaredFields();
                    for (Field field : fields) {
                        field.setAccessible(true);
                        table.addCell(toPdfPCell(field.get(obj).toString(),Element.ALIGN_CENTER));
                    }
                }
            }
            //把表格加入到文档中
            document.add(table);
            //关闭文档
            document.close();
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public  static PdfPCell toPdfPCell(String name, int align) throws DocumentException, IOException {
        // 中文字体
        BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        // 内容字体
        Font fontChinese = new Font(bfChinese, 11, Font.NORMAL);
        PdfPCell cell=new PdfPCell(new Paragraph(name,fontChinese));
        // 设置内容水平居中显示
        cell.setHorizontalAlignment(align);
        // 设置垂直居中
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        return cell;
    }

    /**
     * 给PDF文件加水印
     * @param inputFile 操作的文件位置
     * @param outputFile 生成的文件位置
     * @param date  水印内容
     * @param user 水印内容
     */
    public static void waterMark(String inputFile, String outputFile, String date,String user) {
        try {
            PdfReader reader = new PdfReader(inputFile);
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFile));

            BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
            Rectangle pageRect = null;
            PdfGState gs = new PdfGState();
            gs.setFillOpacity(0.3f);
            gs.setStrokeOpacity(0.4f);
            int total = reader.getNumberOfPages() + 1;

            JLabel label = new JLabel();
            FontMetrics metrics;
            int textH = 0;
            int textW = 0;
            label.setText(date);
            metrics = label.getFontMetrics(label.getFont());
            textH = metrics.getHeight();
            textW = metrics.stringWidth(label.getText());

            PdfContentByte under;
            for (int i = 1; i < total; i++) {
                under = stamper.getOverContent(i);
                under.saveState();
                under.setGState(gs);
                under.beginText();
                under.setFontAndSize(base, 18);
                //水印位置坐标
                int dateHeight = 20;
                int dateWidth = 520;
                int userHeight = 40;
                int userWidth = 560;
                // 水印文字成0度角倾斜
                under.showTextAligned(Element.ALIGN_LEFT, user, userWidth - textW,
                        userHeight - textH, 0);
                under.showTextAligned(Element.ALIGN_LEFT, date, dateWidth - textW,
                        dateHeight - textH, 0);
                under.endText();
            }
            //关闭流
            stamper.close();
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 进行PDF文件下载
     * @param filename 服务器文件
     * @param exportFileName 下载到客户端的文件名
     * @param response
     */
    public void downloadPDF(String filename,String exportFileName, HttpServletResponse response){

        InputStream input = null;
        OutputStream out = null;
        try {
            input=new FileInputStream(filename);
            response.reset();
            response.setContentType("application/pdf");
            response.addHeader("Content-Disposition", "attachment;filename=\""
                    + new String(exportFileName.getBytes("utf-8"), "ISO_8859_1") + "\"");
            response.addHeader("Content-Length", "" + input.available());
            out = response.getOutputStream();
            IOUtils.copy(input, out);

        }catch (Exception e){
          e.printStackTrace();
        }
        finally {
            IOUtils.closeQuietly(input);
            IOUtils.closeQuietly(out);
        }

    }
}

           

测试实体类Student:

public class Student {
    private String name;
    private String gender;
    private String phone;
    private String studentId;
    private String math;
    private String english;

    public String getMath() {
        return math;
    }

    public void setMath(String math) {
        this.math = math;
    }

    public String getEnglish() {
        return english;
    }

    public void setEnglish(String english) {
        this.english = english;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getStudentId() {
        return studentId;
    }

    public void setStudentId(String studentId) {
        this.studentId = studentId;
    }
}
           

测试方法:

public class Test {
    public static void main(String[] args) {
        Test test=new Test();
        test.test();
    }
    private void test(){
        List<Student> list=new ArrayList();
        for (int i=0;i<=5;i++){
            Student student=new Student();
            student.setGender("男");
            student.setName("张三");
            student.setPhone("1320818027"+i);
            student.setStudentId("20153106059"+i);
            student.setMath("9"+i);
            student.setEnglish("8"+i);
            list.add(student);
        }
        String title="成绩单";
        //这里需要保持标题数组的顺序和Student中定义的顺序一致
        String[] columnHeaders={"姓名","性别","电话","学号","数学","英语"};
        try {
            //生成PDF文件,不带水印
            PdfUtil.generatePdfFile(list,"E:\\File\\student.pdf",title,columnHeaders);
            //给刚才生成的PDF文件加水印(时间+用户)
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String date=sdf.format(new Date());
            PdfUtil.waterMark("E:\\File\\student.pdf","E:\\File\\studentwater.pdf",date,"debruyne");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
	
}
           

不带 水印的文件student.pdf:

java实现PDF报表生成通用工具类

带水印的文件studentwater.pdf:

java实现PDF报表生成通用工具类

附前端下载方法:

fileDownload: function(action) {
      var formNode = document.createElement('form');
      var formId = new Date().getTime();
      formNode.id = formId;
      formNode.method = 'post';
      formNode.action = action;
      $('body').append(formNode);
      $('#' + formId).submit();
    }  
 $(document).on('click', '.j-decisionfiledownload-btn', function() {
    util.fileDownload('路径/'+ 参数);
  });