1、Pdf创建修改

公众号有一个用户在线签名生成合同的功能。当时将用户信息自动填充到合同中,以及用户签名填充到合同中,就有用到这些东西,只是那个时候没有进行总结,这次因为之前生成的合同一直都不具备有法律效率,所以要重新进行开发,依赖第三方具有法律认证的公司,并且添加了盖章的功能。

首先之前自己的写法,往pdf模板中填充内容。创建pdf的模板,用软件 Acrobat ,选择工具----》准备表单------》选择需要生成的pdf然后创建输入框,并且给每个需要填充的输入框起一个名字。注意这里需要指定字体的类型,否则最后生成的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>

操作代码:

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.eclipse.jdt.internal.compiler.batch.Main;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.log.SysoCounter;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.tl.weixin.GlobalVar;
import epm.core.webservice.sgcscws.CommonDataServiceProxy;
* 娴嬭瘯  鍏ュ弬map鐢熸垚
* @author MJX
public class PdfMakeTest {
// 入参传的一个是 key value 形式的 map 填充的文字内容
    // 另一个传输的是 签字图片转成的 byte数组
    //生成 base64 pdf  过户 更改
        public String sendpdfGh(Map<String, String> content, byte[] imgb) {
            String strBase64 = null;
            try {
                String fieldName = "contractQz";
                // filePath 是 模板的路径信息 可以注意下面 被转换成了reader 所以不是具体的位置也可以,可以转成其他的方式 存储最后转成 reader的形式就行
                String filePath = this.getClass().getClassLoader().getResource("/").getPath();
                //System.out.println(filePath);
//                String filePath = "D:\\jmgh.pdf";
                //PdfReader reader = new PdfReader(new FileInputStream(new  File(filePath)));
                filePath = filePath + content.get("pdfVersion");
                PdfReader reader = new PdfReader(filePath);
            // 输出流 是为了接 转换的pdf 模板
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                PdfStamper psf = new PdfStamper(reader, bos);
                PdfContentByte under = psf.getUnderContent(1);
                // 创建字体
                BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
                ArrayList fontList = new ArrayList();
                fontList.add(bf);
                AcroFields fields = psf.getAcroFields();
                 // 设置生成时候的字体
                fields.setSubstitutionFonts(fontList);
                // 循环 key  value 根据key  查找模板中的隐藏域 然后将value填充
                for (String key : content.keySet()) {
                    String value = (String) content.get(key);
                    fields.setField(key, value);
                // fields.setField("USER_NO", cons_no);
                // fields.setField("BASE_TYPE4", "false");
                // fillData(fields, data(cusdeal));
                // 以下 是改良的 填充 签名 信息
            // 因为签名是一个 图片 直接填充的时候 会 有位置不对应的问题
            // 怀疑是 上面的 PdfContentByte under = psf.getUnderContent(1); 参数获取的是1 的问题
                // 获取表单中的 所有 隐藏域名字
                AcroFields form = psf.getAcroFields();
                //获取 关键字在第几页的 页数
                int pageNo = form.getFieldPositions(fieldName).get(0).page;
                // 根据 关键字 获取 签名区域 并定位到 位置的 坐标
                Rectangle signRect = ((AcroFields.FieldPosition) fields.getFieldPositions(fieldName).get(0)).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                Image image = null;
                // image = Image.getInstance(signature_url + "/" + cons_no + ".png");
                 // 获取 image  的图片对象
                image = Image.getInstance(imgb);
                //设置第几页的添加
                PdfContentByte under2 = psf.getOverContent(pageNo);
                // 依据 模板中的 长宽 设置 图片的长宽
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                // 设置图片的坐标 并且 under2 添加图片
                image.setAbsolutePosition(x, y);
                under2.addImage(image);
                //  完结
                psf.setFormFlattening(true);
                psf.close();
                // 因为 上面 将pdf写入到了输出流中 相当于一直在操作流
                // 所以 这里可以直接将流 进行转换 base64 返回 也可以 转成 本地的 图片  直接操作 bos 输出流就可以
                strBase64 = Base64.encodeBase64String(bos.toByteArray());
            //    System.out.println(strBase64);
                bos.close();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
            return strBase64;
            //return rtncode + "," + rtnMsg;
}

以上就是依据模板生成的 pdf,并且是base64形式的可进行传输当然,模板传入也可以动态的传入以上代码可以进行提取,动态可变参数全部提出来。

附带一个转换类,将生成好的base64 转换成pdf文档,验证是否正确。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import sun.misc.BASE64Decoder;
public class BaseToPdf {
     * Description: 将base64编码内容转换为Pdf
     * @param  base64编码内容,文件的存储路径(含文件名)
     * @Author MJX
     * Create Date: 2029年7月30日 
    public static void base64StringToPdf(String base64Content,String filePath){
        BASE64Decoder decoder = new BASE64Decoder();
        BufferedInputStream bis = null;
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
        try {
            byte[] bytes = decoder.decodeBuffer(base64Content);//base64编码内容转换为字节数组
            ByteArrayInputStream byteInputStream = new ByteArrayInputStream(bytes);
            bis = new BufferedInputStream(byteInputStream);
            File file = new File(filePath);
            File path = file.getParentFile();
            if(!path.exists()){
                path.mkdirs();
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            byte[] buffer = new byte[1024];
            int length = bis.read(buffer);
            while(length != -1){
                bos.write(buffer, 0, length);
                length = bis.read(buffer);
            bos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            //closeStream(bis, fos, bos);
    public static void main(String[] args) {
        String kk = "";
        base64StringToPdf(kk,"E:\\cn25.pdf");
}

2、PDF转图片

pdf的转图片的原因是展示用。直接给用户展示pdf PC端和安卓(安卓有的可以用,有的可以下载)直接用a标签然后跟pdf的路径就可以,但是在IOS上 没有办法。== 坑了因为做的是移动端的还必须各种兼容。前台使用pdfjs进行渲染,发现小的pdf文档还可以接受,但是大一点的就GG 了。渲染的时间太长,好久都加载不出来。而且没有经过填充的快,但是填充过的pdf文档加载很慢。所以想到了 将pdf 转换成图片的方式,前台拿到图片的数组,然后一张一张的展示图片的base64 这样浏览器直接渲染,速度会大幅度的提升。第三方厂家提供了 pdf 转图片的功能,不知道是传输过程的问题,还是厂家转换的问题。速度太慢。自己百度了一套。pdfbox 阿帕奇的工具,依赖windows的字体库,linux需要自己装字体。

依赖:

<!--pdf 压缩 信息 begin -->
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>fontbox</artifactId>
    <version>2.0.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox -->
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
</dependency>
<!--pdf 压缩 信息 end  -->
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
* ChangePdfOne
* @author MJX
* @date 2020/5/6
public class ChangePdfOne {
     * 转换全部的pdf
     * @param type 图片类型
        pdfStr:pdf的base64
        type 是图片类型
    public static List pdf2png(String pdfStr, String type) {
        // 将pdf装图片 并且自定义图片得格式大小
//        File file = new File(fileAddress+"\\"+filename+".pdf");
        byte[] decode = Base64.getDecoder().decode(pdfStr);
        try {
            PDDocument doc = PDDocument.load(decode);
//            PDDocument doc = PDDocument.load(file);
            PDFRenderer renderer = new PDFRenderer(doc);
            int pageCount = doc.getNumberOfPages();
            ArrayList<String> list = new ArrayList<>();
            for (int i = 0; i < pageCount; i++) {
                // 控制清晰度 后面的100 值越大越清晰 
                BufferedImage image = renderer.renderImageWithDPI(i, 100); // Windows native DPI
                // BufferedImage srcImage = resize(image, 240, 240);//产生缩略图
//                ImageIO.write(image, type, new File(fileAddress+"\\"+filename+"_"+(i+1)+"."+type));
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ImageIO.write(image,type,bos);
                byte[] bytes = bos.toByteArray();
                String base = Base64.getEncoder().encodeToString(bytes);
                list.add(base);
//                System.out.println("base = " + base);
//                File file = new File("D:\\testAnySignEncPackage\\"+ i +"."+"jpg");
//                FileUtils.writeByteArrayToFile(file, bytes);
            return list;
        } catch (IOException e) {
            e.printStackTrace();
        return null;
    public static void main(String[] args) {
        pdf2png("","jpg");
}

生成的图片有乱码的情况,百度发现大多说的都是字体不完全,需要安装字体库。找了好久 最终也没有找到 mstmc.ttf 的字体在哪里安装==。


java通过poi导出excel和pdf
由于各户的需求,所以需要增加导出excel这个功能,其实大部分系统都需要这个导出功能的,所以这里也就不详细说明具体导出的背景了O(∩_∩)O~
如果你想在Java中将网页链接转换为PDF,可以使用第三方库,比如 iText。以下是一个使用iText的示例代码
如果你想在Java中将网页链接转换为PDF,可以使用第三方库,比如 iText。以下是一个使用iText的示例代码
我把Github上最牛b的Java教程和实战项目整合成了一个PDF文档
大家都知道 Github 是一个程序员福地,这里有各种厉害的开源框架、软件或者教程。这些东西对于我们学习和进步有着莫大的进步,所以我有了这个将 Github 上非常棒的 Java 开源项目整理下来的想法。觉得不错的话,欢迎小伙伴们去star一波。 很多小伙伴都不知道学习什么开源项目,这篇文章定能为你解决疑惑。
GitHub上标星75k+超牛的《Java面试突击版》,分享PDF离线版
不论是校招还是社招都避免不了各种面试。笔试,如何去准备这些东西就显得格外重要。不论是笔试还是面试都是有章可循的,我这个有章可循‘说的意思只是说应对技术面试是可以提前准备。
由于细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容! 整理了一份Java核心知识点。覆盖了JVM、锁、并发、Java反射、Spring原理、微服务、Zookeeper、数据库、数据结构等大量知识点。
java实现pdf电子合同设置合同编号
现在有一些用户信息合同,要求在合同上添加合同编号,合同编号要求按照一定规则系统生成.看过很多同学的实现方案,也尝试过很多,为了方便以后有同样需求的同学可以节省时间,进行了相关内容的梳理.