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的字体在哪里安装==。


目录
相关文章
|
22天前
|
Java
Java开发实现图片URL地址检验,如何编码?
【10月更文挑战第14天】Java开发实现图片URL地址检验,如何编码?
53 4
|
24天前
|
前端开发
PDF文件上传转成base64编码并支持预览
PDF文件上传转成base64编码并支持预览
107 12
|
22天前
|
Java
Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
【10月更文挑战第14天】Java开发实现图片地址检验,如果无法找到资源则使用默认图片,如何编码?
49 2
|
29天前
|
算法 Java Linux
java制作海报二:java使用Graphics2D 在图片上合成另一个照片,并将照片切割成头像,头像切割成圆形方法详解
这篇文章介绍了如何使用Java的Graphics2D类在图片上合成另一个照片,并将照片切割成圆形头像的方法。
45 1
java制作海报二:java使用Graphics2D 在图片上合成另一个照片,并将照片切割成头像,头像切割成圆形方法详解
|
22天前
|
Java 数据安全/隐私保护
Java ffmpeg 实现视频加文字/图片水印功能
【10月更文挑战第22天】在 Java 中使用 FFmpeg 实现视频加文字或图片水印功能,需先安装 FFmpeg 并添加依赖(如 JavaCV)。通过构建 FFmpeg 命令行参数,使用 `drawtext` 滤镜添加文字水印,或使用 `overlay` 滤镜添加图片水印。示例代码展示了如何使用 JavaCV 实现文字水印。
|
23天前
|
Java Apache Maven
Java将word文档转换成pdf文件的方法?
【10月更文挑战第13天】Java将word文档转换成pdf文件的方法?
112 1
|
28天前
|
前端开发 小程序 Java
java基础:map遍历使用;java使用 Patten 和Matches 进行正则匹配;后端传到前端展示图片三种情况,并保存到手机
这篇文章介绍了Java中Map的遍历方法、使用Pattern和matches进行正则表达式匹配,以及后端向前端传输图片并保存到手机的三种情况。
17 1
|
29天前
|
算法 Java Linux
java制作海报四:java BufferedImage 转 InputStream 上传至OSS。png 图片合成到模板(另一个图片)上时,透明部分变成了黑色
这篇文章主要介绍了如何将Java中的BufferedImage对象转换为InputStream以上传至OSS,并解决了png图片合成时透明部分变黑的问题。
50 1
|
29天前
|
算法 搜索推荐 Java
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
这篇文章介绍了如何使用Java后端技术,结合Graphics2D和Echarts等工具,生成包含个性化信息和图表的海报,并提供了详细的代码实现和GitHub项目链接。
96 0
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
|
29天前
|
算法 小程序 Java
java制作海报三:获取微信二维码详情,并改变大小,合成到海报(另一张图片)上
这篇文章介绍了如何使用Java获取微信小程序的二维码,并将其调整大小后合成到海报(另一张图片)上。
37 0
下一篇
无影云桌面