各位亲爱的小伙伴们,你们好呀,我是罗少,感谢你们的支持,今天我又来跟你唠嗑了。
程序员可能经常会要写一些文档之类的东西交付给别人,一般我们都是用word写,提供的时候是PDF格式的,因为PDF不容易被编辑篡改。我们经常就是右键保存选择保存为PDF格式(很多自带的编辑器都自带转换功能),是不是觉得很好用。那么用代码怎么来实现呢?刚好曾经做项目就有这个需求,经理让我去研究一下,找遍了资料,遇到了很多坑,搞了一个礼拜才解决。现在拿出来跟大家分享一下。
我又要开启斗图模式了,别慌!
-
图片转PDF
(1)新建一个工程maven(以上默认你会)-> 引入依赖包
com.itextpdfitextpdf5.5.5
(2)新建一个service
由于我们是简单的例子,没有直接从前端传输文件到后端(该步骤本文省略),直接后端用文件路径,实际项目中肯定是要从前端传入文件到后端的,后端再进行解析
package jp.service.impl;
import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfWriter;
import jp.service.IFileHandleService;
import jp.utils.ResultVoUtil;
import jp.vo.ResultVo;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;@Servicepublic class FileHandleImpl implements IFileHandleService {private static final int regular_width = 842;
private static final int regular_height = 595;
private static final int vertical_regular_width = 595;
private static final int vertical_regular_height = 842;@Overridepublic ResultVo fileToPdf() {
String imagPath = "D:/test.jpg";//图片文件存放的地址String pdfOutPath = "D:/test.pdf";//输出PDF的路径
boolean result = imgToPdf(imagPath, pdfOutPath);
if(result)ResultVoUtil.success();
return ResultVoUtil.error("0001", "转换失败");}private boolean imgToPdf(String imagPath, String pdfOutPath) {boolean changeResult = false;
try {
FileOutputStream fos = new FileOutputStream(pdfOutPath);Document doc = new Document(null, 0, 0, 0, 0);// 写入PDF文档PdfWriter.getInstance(doc, fos);// 读取图片流BufferedImage img = null;// 实例化图片Image image = null;
float newHeight = 0f, newWidth = 0f;img = ImageIO.read(new File(imagPath));Map,Float> result = setImageWidthHeight(img.getWidth(), img.getHeight(),newWidth, newHeight);newWidth = result.get("width");newHeight = result.get("height");doc.setPageSize(new Rectangle(newWidth,newHeight));image = Image.getInstance(imagPath);image.scaleAbsolute(new Rectangle(newWidth,newHeight));// 添加图片到文档doc.newPage();doc.open();doc.add(image);// 关闭文档doc.close();changeResult = true;System.out.println("图片转PDF成功");} catch (Exception e) {
System.out.println("图片转PDF失败");e.printStackTrace();}return changeResult;}/**
* 设置PDF的宽高*
* @param width* @param height* @param newWidth* @param newHeight* @return*/private Map, Float> setImageWidthHeight(float width, float height, float newWidth, float newHeight) {float res = width / height;
if (res >= 1) { //横向if (width > regular_width) {
newWidth = regular_width;newHeight = (regular_width / width) * height;} else if (height > regular_height) {
newHeight = regular_height;newWidth = (regular_height / height) * width;} else {//如果都在范围内,不做任何操作newWidth = width;newHeight = height;}
} else {if (width > vertical_regular_width) {
newWidth = vertical_regular_width;newHeight = (vertical_regular_width / width) * height;} else if (height > vertical_regular_height) {
newHeight = vertical_regular_height;newWidth = (vertical_regular_height / height) * width;} else {//如果都在范围内,不做任何操作newWidth = width;newHeight = height;}
}
Map, Float> result = new HashMap, Float>();result.put("width", newWidth);result.put("height", newHeight);
return result;}
}
package jp.service;
import jp.vo.ResultVo;
public interface IFileHandleService {
ResultVo fileToPdf();}
备注:这些图片的宽度和高度,都是前人经过大量实现的出来比较符合原图片大小的值,如果没有必要的话,可以不需要修改。默认这些就可以,如果你应该兴趣可以自行修改,然后看看效果
private static final int regular_width = 842;
private static final int regular_height = 595;
private static final int vertical_regular_width = 595;
private static final int vertical_regular_height = 842;
我们来看一下实际效果。
我在D盘创建了一个test.jpg文件,代码设置输出结果路径为D:/test.pdf
点击程序运行,看一下效果
此时在D盘生成了pdf文件,同时PDF阅读器打开,可以发现他的比率和清洗都都跟原图片类似。
想不想自己动手试试?
2.doc转PDF
doc文档转PDF就相对复杂了,需要引用外部控件jacob
jacob依赖包下载:
https://github.com/freemansoft/jacob-project/releases
以前依赖包可以直接在jacob官网下载,现在你去下载的话只能下载个README.md文件
解压下载得包,可以看到理念有三个比较重要得文件
jacob.jar:Java工程中使用;
jacob-1.20-x64.dll:放在windows系统为64的Java目录 jdk/jre/bin目录。
jacob-1.20-x32.dll:放在windows系统为32的Java目录 jdk/jre/bin目录。
例如:C:\Program Files\Java\jdk1.8.0_121\jre\bin
jacob-1.20-x64.dll、jacob-1.20-x32.dll 根据自己的电脑版本数选择
切记,一定加加上dll文件以及工程中依赖jar包;如果忘记加上dll,程序启动的时候不会报错,
但是在执行的时候会抛异常,如果你没打出异常的话,你会一脸懵逼的不知道哪里出错了
贴上代码:
private boolean docFileToPdf(String docPath, String pdfOutPath) {
Boolean changeResult = false;ActiveXComponent app = null;
try{//打开word应用程序app = new ActiveXComponent("Word.Application");//设置word不可见app.setProperty("Visible", false);//获得word中所有打开的文档,返回Documents对象Dispatch docs = app.getProperty("Documents").toDispatch();//调用Documents对象中Open方法打开文档,并返回打开的文档对象DocumentDispatch doc = Dispatch.call(docs,"Open",docPath,
false,
true).toDispatch();//调用Document对象的SaveAs方法,将文档保存为pdf格式Dispatch.call(doc,"ExportAsFixedFormat",pdfOutPath,wdFormatPDF //word保存为pdf格式宏,值为17);//关闭文档Dispatch.call(doc, "Close",false);System.out.println("doc文档转PDF成功");changeResult = true;} catch (Exception e) {
System.out.println("doc文档转PDF失败");e.printStackTrace();}return changeResult;}
下面我们来看一下效果:
同样在D盘我们新建一个docx文档,内容如下,输出路径设置为D:/woshiluoshao.pdf
启动程序看看效果
以上只是我举的两个例子,图片支持:png、jpg、jpeg、gif等标准格式图片
doc文档支持doc、docx
其他比如excel、office等我没有举例。
是不是成功生成了。你以为这就结束了吗?不,还没有,还有一些隐藏的坑,我要慢慢跟你道来!
潜藏的坑:
(1)文件转PDF如果是doc等格式转换的话,只能在windows下部署运行,不能部署到linux下
(2)出现doc、excel等格式转换的前提,必须要先安装微软office软件,不然运行会报错
(3)如果出现错误:VariantChangeType failed 这个类型错误,处理方案如下:
1.mmc comexp.msc -64
2.组件服务-》我的电脑-》DCOM配置-》Microsoft Word 97 – 2003 文档-》标识改成交互式用户
如果上诉还是不行,在C:\Windows\System32\config\systemprofile下创建文件夹Desktop即可
(4)jacob支持tomcat8.0以上版本、jdk1.8及以上版本,如果版本太低,也可能报错
代码不易,总结不易,且写且珍惜;各位看官,且看且珍惜,给个赞再走吧。
贴上我的公众号,喜欢请帮我推荐,谢谢