java 对PDF的操作(生成,转换,转图片,转base64等)

简介: java 对PDF的操作(生成,转换,转图片,转base64等)

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>

操作代码:

importjava.io.ByteArrayOutputStream;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.StringReader;
importjava.util.ArrayList;
importjava.util.HashMap;
importjava.util.Map;
importorg.apache.commons.codec.binary.Base64;
importorg.eclipse.jdt.internal.compiler.batch.Main;
importcom.itextpdf.text.Image;
importcom.itextpdf.text.Rectangle;
importcom.itextpdf.text.log.SysoCounter;
importcom.itextpdf.text.pdf.AcroFields;
importcom.itextpdf.text.pdf.BaseFont;
importcom.itextpdf.text.pdf.PdfContentByte;
importcom.itextpdf.text.pdf.PdfReader;
importcom.itextpdf.text.pdf.PdfStamper;
importcom.tl.weixin.GlobalVar;
importepm.core.webservice.sgcscws.CommonDataServiceProxy;
/**** 娴嬭瘯  鍏ュ弬map鐢熸垚* @author MJX**/publicclassPdfMakeTest {
// 入参传的一个是 key value 形式的 map 填充的文字内容// 另一个传输的是 签字图片转成的 byte数组//生成 base64 pdf  过户 更改publicStringsendpdfGh(Map<String, String>content, byte[] imgb) {
StringstrBase64=null;
try {
StringfieldName="contractQz";
// filePath 是 模板的路径信息 可以注意下面 被转换成了reader 所以不是具体的位置也可以,可以转成其他的方式 存储最后转成 reader的形式就行StringfilePath=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");
PdfReaderreader=newPdfReader(filePath);
// 输出流 是为了接 转换的pdf 模板ByteArrayOutputStreambos=newByteArrayOutputStream();
PdfStamperpsf=newPdfStamper(reader, bos);
PdfContentByteunder=psf.getUnderContent(1);
// 创建字体BaseFontbf=BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
ArrayListfontList=newArrayList();
fontList.add(bf);
AcroFieldsfields=psf.getAcroFields();
// 设置生成时候的字体fields.setSubstitutionFonts(fontList);
// 循环 key  value 根据key  查找模板中的隐藏域 然后将value填充for (Stringkey : content.keySet()) {
Stringvalue= (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 的问题// 获取表单中的 所有 隐藏域名字AcroFieldsform=psf.getAcroFields();
//获取 关键字在第几页的 页数intpageNo=form.getFieldPositions(fieldName).get(0).page;
// 根据 关键字 获取 签名区域 并定位到 位置的 坐标RectanglesignRect= ((AcroFields.FieldPosition) fields.getFieldPositions(fieldName).get(0)).position;
floatx=signRect.getLeft();
floaty=signRect.getBottom();
Imageimage=null;
// image = Image.getInstance(signature_url + "/" + cons_no + ".png");// 获取 image  的图片对象image=Image.getInstance(imgb);
//设置第几页的添加PdfContentByteunder2=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 (Exceptione) {
e.printStackTrace();
            } finally {
            }
returnstrBase64;
//return rtncode + "," + rtnMsg;        }
}

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

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

importjava.io.BufferedInputStream;
importjava.io.BufferedOutputStream;
importjava.io.ByteArrayInputStream;
importjava.io.File;
importjava.io.FileOutputStream;
importsun.misc.BASE64Decoder;
publicclassBaseToPdf {
/*** Description: 将base64编码内容转换为Pdf* @param  base64编码内容,文件的存储路径(含文件名)* @Author MJX* Create Date: 2029年7月30日 */publicstaticvoidbase64StringToPdf(Stringbase64Content,StringfilePath){
BASE64Decoderdecoder=newBASE64Decoder();
BufferedInputStreambis=null;
FileOutputStreamfos=null;
BufferedOutputStreambos=null;
try {
byte[] bytes=decoder.decodeBuffer(base64Content);//base64编码内容转换为字节数组ByteArrayInputStreambyteInputStream=newByteArrayInputStream(bytes);
bis=newBufferedInputStream(byteInputStream);
Filefile=newFile(filePath);
Filepath=file.getParentFile();
if(!path.exists()){
path.mkdirs();
            }
fos=newFileOutputStream(file);
bos=newBufferedOutputStream(fos);
byte[] buffer=newbyte[1024];
intlength=bis.read(buffer);
while(length!=-1){
bos.write(buffer, 0, length);
length=bis.read(buffer);
            }
bos.flush();
        } catch (Exceptione) {
e.printStackTrace();
        }finally{
//closeStream(bis, fos, bos);        }
    }
publicstaticvoidmain(String[] args) {
Stringkk="";
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-->
importorg.apache.pdfbox.pdmodel.PDDocument;
importorg.apache.pdfbox.rendering.PDFRenderer;
importjavax.imageio.ImageIO;
importjava.awt.image.BufferedImage;
importjava.io.ByteArrayOutputStream;
importjava.io.IOException;
importjava.util.ArrayList;
importjava.util.Base64;
importjava.util.List;
/*** ChangePdfOne** @author MJX* @date 2020/5/6*/publicclassChangePdfOne {
/*** 转换全部的pdf* @param type 图片类型pdfStr:pdf的base64type 是图片类型*/publicstaticListpdf2png(StringpdfStr, Stringtype) {
// 将pdf装图片 并且自定义图片得格式大小//        File file = new File(fileAddress+"\\"+filename+".pdf");byte[] decode=Base64.getDecoder().decode(pdfStr);
try {
PDDocumentdoc=PDDocument.load(decode);
//            PDDocument doc = PDDocument.load(file);PDFRendererrenderer=newPDFRenderer(doc);
intpageCount=doc.getNumberOfPages();
ArrayList<String>list=newArrayList<>();
for (inti=0; i<pageCount; i++) {
// 控制清晰度 后面的100 值越大越清晰 BufferedImageimage=renderer.renderImageWithDPI(i, 100); // Windows native DPI// BufferedImage srcImage = resize(image, 240, 240);//产生缩略图//                ImageIO.write(image, type, new File(fileAddress+"\\"+filename+"_"+(i+1)+"."+type));ByteArrayOutputStreambos=newByteArrayOutputStream();
ImageIO.write(image,type,bos);
byte[] bytes=bos.toByteArray();
Stringbase=Base64.getEncoder().encodeToString(bytes);
list.add(base);
//                System.out.println("base = " + base);//                File file = new File("D:\\testAnySignEncPackage\\"+ i +"."+"jpg");//                FileUtils.writeByteArrayToFile(file, bytes);            }
returnlist;
        } catch (IOExceptione) {
e.printStackTrace();
        }
returnnull;
    }
publicstaticvoidmain(String[] args) {
pdf2png("","jpg");
    }
}

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


目录
相关文章
|
2月前
|
XML 缓存 JSON
为什么浏览器中有些图片、PDF等文件点击后有些是预览,有些是下载
为什么浏览器中有些图片、PDF等文件点击后有些是预览,有些是下载
148 0
|
8天前
|
Java
Java-FileInputStream和FileOutputStream的使用,txt文件及图片文件的拷贝
这篇文章介绍了Java中FileInputStream和FileOutputStream的使用,包括如何读取和写入txt文件以及如何拷贝图片文件。
Java-FileInputStream和FileOutputStream的使用,txt文件及图片文件的拷贝
|
11天前
|
存储 缓存 监控
Java——图片文件位于 bin 目录下,下载新图片会导致应用程序重启
【9月更文挑战第22天】在Java应用中,若图片位于bin目录下且下载新图片导致应用重启,可能是因为部署方式不当或资源监控机制过于敏感。解决方法包括:更改图片存储位置至独立目录;配置应用服务器减少资源监控敏感度;使用独立资源服务器托管静态资源;优化代码减少资源重复加载。具体方案需根据应用实际情况和技术栈调整。
|
2月前
|
Java
Java系列之 重命名文件/图片,renameTo() 方法的使用
这篇文章介绍了Java中File类的renameTo()方法,包括其使用方式、参数、返回值以及一些使用时的注意事项,并通过示例代码演示了如何使用该方法来重命名文件。
Java系列之 重命名文件/图片,renameTo() 方法的使用
|
7天前
|
Python
Python办公自动化:提取pdf文件中的图片
Python办公自动化:提取pdf文件中的图片
10 0
|
1月前
|
数据采集 存储 前端开发
Java爬虫开发:Jsoup库在图片URL提取中的实战应用
Java爬虫开发:Jsoup库在图片URL提取中的实战应用
|
2月前
|
数据安全/隐私保护 Python Windows
三种方法,Python轻松提取PDF中全部图片
三种方法,Python轻松提取PDF中全部图片
|
2月前
|
存储 安全 Java
"Java编码魔法:揭秘图片与文件的Base64神秘转换术,让数据在指尖跳跃!"
【8月更文挑战第16天】Base64编码在Java开发中常用于将二进制数据如图片转换为ASCII字符串以便传输。编码使用64个字符及等号填充,每3字节数据编码为4个字符。Java利用`java.util.Base64`类实现此功能:读取图片或文件为字节数组后进行编码。解码时将Base64字符串还原为字节数组并写入文件。需注意编码效率降低、不提供安全性及特殊字符兼容性等问题。掌握这些技巧有助于解决Web开发中的数据传输需求。
62 4
|
2月前
|
Python
Python——批量将PDF文件转为图片
Python——批量将PDF文件转为图片
32 2
|
3月前
|
存储 Java 索引
Java ArrayList操作指南:如何移除并返回第一个元素
通过上述方法,你可以方便地从Java的 `ArrayList` 中移除并返回第一个元素。这种操作在日常编程中非常常见,是处理列表时的基本技能之一。希望这篇指南能帮助你更好地理解和运用Java的 `ArrayList`。
39 4
下一篇
无影云桌面