ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java生成pdf并加水印

2022-07-14 20:37:34  阅读:272  来源: 互联网

标签:ps java fields new content 加水 import pdf


1生成pdf并通过输出流返回生成的pdf文件(常用于下载pdf)

2生成pdf并上传到minio,并返回图片的url(常用于pdf的预览)

  • 场景梳理

    1 ,根据事先制作好的pdf模板生成pdf(使用Adobe Acrobat软件)

    2, 在用户签名处给pdf加上签名的图片

    3, 给pdf生成水印(水印可换行)

    4, 直接返回输出流给前端,前端直接可以下载pdf

    需要的pom依赖
      <!-- 导出pdf需要使用的包:xdocreport -->
            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itext-asian</artifactId>
                <version>5.2.0</version>
            </dependency>
            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>itextpdf</artifactId>
                <version>5.5.13</version>
            </dependency>
            <dependency>
                <groupId>fr.opensagres.xdocreport</groupId>
                <artifactId>org.apache.poi.xwpf.converter.core</artifactId>
                <version>1.0.4</version>
            </dependency>
            <dependency>
                <groupId>fr.opensagres.xdocreport</groupId>
                <artifactId>org.apache.poi.xwpf.converter.pdf</artifactId>
                <version>1.0.4</version>
            </dependency>
            <dependency>
                <groupId>fr.opensagres.xdocreport</groupId>
                <artifactId>fr.opensagres.xdocreport.itext.extension</artifactId>
                <version>1.0.4</version>
            </dependency>
            <!-- 文件流转化需要的依赖 -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>5.3.20</version>
            </dependency>
    

该方法的代码如下

package com.ruoyi.common.utils;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.AcroFields.Item;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * pdf工具类
 *
 * @author wuhuc
 * @data 2022/7/12 - 9:12
 */
public class PdfUtill {
    /**
     * @param templatePdfPath 模板pdf路径
     * @param data            数据
     */
    public static void generatePDFByOutputStream(String templatePdfPath,
                                                 Map<String, Object> data, Map<String, byte[]> imgMap, HttpServletResponse response) {
        OutputStream fos = null;
        ByteArrayOutputStream bos = null;
        try {
            PdfReader reader = new PdfReader(templatePdfPath);
            bos = new ByteArrayOutputStream();
            /* 将要生成的目标PDF文件名称 */
            PdfStamper ps = new PdfStamper(reader, bos);
            PdfGState gs = new PdfGState();
            gs.setFillOpacity(0.4f);// 设置透明度
            /* 使用中文字体 */
            BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
            fontList.add(bf);
            int total = reader.getNumberOfPages() + 1;
            PdfContentByte content;
            for (int i = 1; i < total; i++) {
                content = ps.getOverContent(i);
                content.beginText();
                content.setGState(gs);
                content.setColorFill(BaseColor.DARK_GRAY); //水印颜色
                content.setFontAndSize(bf, 20); //水印字体样式和大小
                final String username = SecurityUtils.getUsername();
                for (int x = 0; x < 700; x = x + 300) {
                    for (int y = 0; y < 900; y = y + 200) {
                        //水印内容和水印位置
                        content.showTextAligned(Element.ALIGN_CENTER, "xxx", x - 20, y + 10, 30);
                        content.showTextAligned(Element.ALIGN_CENTER, username + LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_PATTERN), x, y, 30);
                    }
                }
                content.endText();
            }

            /* 取出报表模板中的所有字段 */
            AcroFields fields = ps.getAcroFields();
            fields.setSubstitutionFonts(fontList);
            fillData(fields, data);
            // 添加图片
            if (imgMap != null) {
                addImage(ps, fields, imgMap);
            }
            /* 必须要调用这个,否则文档不会生成的  如果为false那么生成的PDF文件还能编辑,一定要设为true*/
            ps.setFormFlattening(true);
            ps.close();
            //设置导出的数据的文件流
            response.setContentType("application/pdf");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("xxx", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".pdf");
            fos = response.getOutputStream();
            fos.write(bos.toByteArray());
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static AjaxResult generatePDFByMinio(String templatePdfPath,
                                                Map<String, Object> data, Map<String, byte[]> imgMap) {
        ByteArrayOutputStream bos = null;
        try {
            PdfReader reader = new PdfReader(templatePdfPath);
            bos = new ByteArrayOutputStream();
            /* 将要生成的目标PDF文件名称 */
            PdfStamper ps = new PdfStamper(reader, bos);
            PdfGState gs = new PdfGState();
            gs.setFillOpacity(0.4f);// 设置透明度
            /* 使用中文字体 */
            BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
            fontList.add(bf);
            int total = reader.getNumberOfPages() + 1;
            PdfContentByte content;
            for (int i = 1; i < total; i++) {
                content = ps.getOverContent(i);
                content.beginText();
                content.setGState(gs);
                //水印颜色
                content.setColorFill(BaseColor.DARK_GRAY);
                //水印字体样式和大小
                content.setFontAndSize(bf, 20);
                final String username = SecurityUtils.getUsername();
                for (int x = 0; x < 700; x = x + 300) {
                    for (int y = 0; y < 900; y = y + 200) {
                        //水印内容和水印位置
                        content.showTextAligned(Element.ALIGN_CENTER, "xxx", x - 20, y + 10, 30);
                        content.showTextAligned(Element.ALIGN_CENTER, username + LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.NORM_DATETIME_PATTERN), x, y, 30);
                    }
                }
                content.endText();
            }
            /* 取出报表模板中的所有字段 */
            AcroFields fields = ps.getAcroFields();
            fields.setSubstitutionFonts(fontList);
            fillData(fields, data);
            // 添加图片
            if (imgMap != null) {
                addImage(ps, fields, imgMap);
            }
            /* 必须要调用这个,否则文档不会生成的  如果为false那么生成的PDF文件还能编辑,一定要设为true*/
            ps.setFormFlattening(true);
            ps.close();
            final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray());
            MultipartFile file = new MockMultipartFile("xxx.pdf", "xxx.pdf", "application/pdf", byteArrayInputStream);
            String fileName = FileUploadUtils.uploadMinio(file);
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", fileName);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            return ajax;
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error(e.getMessage());
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void fillData(AcroFields fields, Map<String, Object> data) throws IOException, DocumentException, DocumentException {
        List<String> keys = new ArrayList<String>();
        Map<String, Item> formFields = fields.getFields();
        for (String key : data.keySet()) {
            if (formFields.containsKey(key)) {
                //忽略值为null的字段
                if (data.get(key) != null) {
                    String value = String.valueOf(data.get(key));
                    fields.setField(key, value, true); // 为字段赋值,注意字段名称是区分大小写的
                    keys.add(key);
                }
            }
        }
        Iterator<String> itemsKey = formFields.keySet().iterator();
        while (itemsKey.hasNext()) {
            String itemKey = itemsKey.next();
            if (!keys.contains(itemKey)) {
                fields.setField(itemKey, " ");
            }
        }
    }

    private static void addImage(com.itextpdf.text.pdf.PdfStamper ps, com.itextpdf.text.pdf.AcroFields fields, Map<String, byte[]> imgMap) throws IOException, com.itextpdf.text.DocumentException {
        for (String key : imgMap.keySet()) {
            int pageNo = fields.getFieldPositions(key).get(0).page;
            Rectangle signRect = fields.getFieldPositions(key).get(0).position;
            float x = signRect.getLeft();
            float y = signRect.getBottom();
            // 读图片
            Image image = Image.getInstance(imgMap.get(key));
            // 获取操作的页面
            PdfContentByte under = ps.getOverContent(pageNo);
            // 根据域的大小缩放图片
            image.scaleToFit(signRect.getWidth(), signRect.getHeight());
            // 添加图片
            image.setAbsolutePosition(x, y);
            under.addImage(image);
        }
    }

}

标签:ps,java,fields,new,content,加水,import,pdf
来源: https://www.cnblogs.com/wuhuac/p/16479179.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有