背景
目前收到一个需求,需要给上传的word和pdf文档添加二维码,防止职工给领导签字时伪造合同,所以提出这个需求,上传的word和pdf添加二维码,然后使用我们的app扫码查看相关的信息。
解决方案
网上查了很多资料,解决方案有很多,最终选择了成都冰蓝科技提供的api,原因是操作相对简单,并且该公司是专门做办公软件的,其他的api也比较丰富。(官网: https://www.e-iceblue.cn/)
开发前准备
1:获取第三方jar包,这里使用的是spire.office.free包3.1.1版本
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.office.free</artifactId>
<version>3.1.1</version>
</dependency>
先去http://repo.e-iceblue.cn/repository/maven-public/,冰蓝的官网下载免费的jar包,然后发布到maven仓库,测试可以先放在本地的仓库里面。发布jar包到公司的maven仓库命令如下:
mvn deploy:deploy-file -DgroupId=e-iceblue -DartifactId=spire.office.free -Dversion=3.1.1 -Dpackaging=jar -Dfile=D:/spire.office.free-3.1.1.jar -Durl=http://192.168.200.39:8088/repository/maven-releases/ -DrepositoryId=maven-releases
(Dfile和Durl自行替换,Dfile是本地jar所在的路径,Durl是私服仓库的地址 )
开始测试
1:新建一个springboot项目,并在pom引入jar包。
2:在启动类直接加入添加二维码的方法(也可以自己加接口来测试),代码如下:
public static void main(String[] args) throws IOException {
SpringApplication.run(TemplateApplication.class, args);
addQrcode();
}
private static void addQrcode() throws IOException {
long timeStamp = new Date().getTime();
//创建PdfDocument对象
Document doc = new Document();
doc.loadFromFile("测试二维码1022.docx");
//获取第一个section
Section section = doc.getSections().get(0);
//使用Spire.Barcode的BarcodeSettings和BarcodeGenerator类创建二维码并保存为图片
BarcodeSettings settings = new BarcodeSettings();
settings.setType(BarCodeType.QR_Code);
// 设置一个域名 用爱路灯app扫描
settings.setData("http://www.whyxzm.com/hetong?id=" +123456);
settings.setData2D("请用爱路灯app扫码");
settings.setX(0.75f);
settings.setLeftMargin(0);
settings.setShowTextOnBottom(true);
settings.setQRCodeECL(QRCodeECL.Q);
settings.setQRCodeDataMode(QRCodeDataMode.Numeric);
BarCodeGenerator generator = new BarCodeGenerator(settings);
Image image = generator.generateImage();
ImageIO.write((RenderedImage) image, "png", new File(timeStamp + "QRCode.png"));
//添加二维码图片到Word页眉
HeaderFooter header = section.getHeadersFooters().getHeader();
Paragraph headerpara = header.addParagraph();
//header.getFirstParagraph().appendPicture(timeStamp + "QRCode.png");
headerpara.appendPicture(timeStamp + "QRCode.png");
headerpara.getFormat().setHorizontalAlignment(HorizontalAlignment.Right);
//保存文档
doc.saveToFile(timeStamp + ".docx", FileFormat.Docx);
doc.dispose();
}
3:测试结果
源文件:
添加二维码后:
4:测试发现一个bug,word获取第一页的页眉有问题,他把每一页的页眉都添加了二维码,但pdf不会有问题。
完整代码
1:以下代码是远程的url获取文件在进行操作pdf和word(支持office和wps,好像蓝山办公软件不支持)
2:正式代码如下
private String addBarCode(ContractmanagementContracDetailsVO vo, AnnexVO annexVO) throws IOException {
long timeStamp = new Date().getTime();
// word文档 包含doc和docx格式
if (annexVO.getAnnexSuffix().contains("doc")) {
// 先将远程的docx文件写到本地
this.downLoadFile(annexVO);
//创建Document对象,加载Word文档
Document doc = new Document();
doc.loadFromFile(annexVO.getFileName());
//获取第一个section
Section section = doc.getSections().get(0);
//使用Spire.Barcode的BarcodeSettings和BarcodeGenerator类创建二维码并保存为图片
BarcodeSettings settings = new BarcodeSettings();
settings.setType(BarCodeType.QR_Code);
// 设置一个域名 用爱路灯app扫描
settings.setData("https://www.whyxzm.com/hetong?id=" + vo.getId());
settings.setData2D("请用爱路灯app扫码");
settings.setX(0.75f);
settings.setLeftMargin(15);
settings.setShowTextOnBottom(true);
settings.setQRCodeECL(QRCodeECL.Q);
settings.setQRCodeDataMode(QRCodeDataMode.Numeric);
BarCodeGenerator generator = new BarCodeGenerator(settings);
Image image = generator.generateImage();
ImageIO.write((RenderedImage) image, "png", new File(timeStamp + "QRCode.png"));
//添加二维码图片到Word页眉
HeaderFooter header = section.getHeadersFooters().getHeader();
Paragraph headerpara = header.addParagraph();
//header.getFirstParagraph().appendPicture(timeStamp + "QRCode.png");
headerpara.appendPicture(timeStamp + "QRCode.png");
headerpara.getFormat().setHorizontalAlignment(HorizontalAlignment.Right);
//保存文档
doc.saveToFile(timeStamp + ".doc", FileFormat.Doc);
doc.dispose();
// 调用上传方法 获取新的上传id
BufferedInputStream in = new BufferedInputStream(new FileInputStream(timeStamp + ".doc"));
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
byte[] temp = new byte[1024];
int size = 0;
while ((size = in.read(temp)) != -1) {
out.write(temp, 0, size);
}
in.close();
List<AnnexAddDto> annexAddDtos = new ArrayList<>();
// 文件byte数组
byte[] content = out.toByteArray();
//文件大小
int fileSize = content.length;
String extend = annexVO.getAnnexSuffix();
AnnexAddDto annexAddDto = new AnnexAddDto();
annexAddDto.setBytes(content);
annexAddDto.setFileName(annexVO.getFileName());
annexAddDto.setAnnexSize(fileSize + "");
annexAddDto.setAnnexSuffix(extend);
annexAddDtos.add(annexAddDto);
// 调用文件上传获取到url
List<AnnexVO> annexVOList = fileObjectUploadClient.uploadFileList(annexAddDtos).getData();
String fileId = annexVOList.get(0).getId().toString();
// 删除本地生成的文件
File qrcodePicture = new File("./" + timeStamp + "QRCode.png");
File docFile = new File("./" + annexVO.getFileName());
File qrcodeDocFile = new File("./" + timeStamp + ".doc");
qrcodePicture.delete();
docFile.delete();
qrcodeDocFile.delete();
out.close();
return fileId;
} else if (annexVO.getAnnexSuffix().contains("pdf")) {
// 先将远程的docx文件写到本地
this.downLoadFile(annexVO);
PdfDocument pdf = new PdfDocument();
pdf.loadFromFile(annexVO.getFileName());
//获取第一页
PdfPageBase page = pdf.getPages().get(0);
//生成二维码图片,绘制到PDF页面
BarcodeSettings settings = new BarcodeSettings();//创建二维码图形
settings.setType(BarCodeType.QR_Code);
settings.setData("http://www.whyxzm.com/hetong?id=" + vo.getId());
settings.setData2D("请用爱路灯app扫码");
settings.setX(0.75f);
settings.setLeftMargin(15);
settings.setShowTextOnBottom(true);
settings.setQRCodeECL(QRCodeECL.Q);
settings.setQRCodeDataMode(QRCodeDataMode.Numeric);
BarCodeGenerator generator = new BarCodeGenerator(settings);
Image image = generator.generateImage();
PdfImage pdfImage = PdfImage.fromImage((BufferedImage) image);//绘制二维码图片到PDF
page.getCanvas().drawImage(pdfImage, PdfPageSize.A4.getWidth() - 140, 20);
//保存PDF文档
pdf.saveToFile(timeStamp + ".pdf");
pdf.dispose();
// 调用上传方法 获取新的文件id
BufferedInputStream in = new BufferedInputStream(new FileInputStream(timeStamp + ".pdf"));
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
byte[] temp = new byte[1024];
int size = 0;
while ((size = in.read(temp)) != -1) {
out.write(temp, 0, size);
}
in.close();
List<AnnexAddDto> annexAddDtos = new ArrayList<>();
// 文件byte数组
byte[] content = out.toByteArray();
//文件大小
int fileSize = content.length;
String extend = annexVO.getAnnexSuffix();
AnnexAddDto annexAddDto = new AnnexAddDto();
annexAddDto.setBytes(content);
annexAddDto.setFileName(annexVO.getFileName());
annexAddDto.setAnnexSize(fileSize + "");
annexAddDto.setAnnexSuffix(extend);
annexAddDtos.add(annexAddDto);
// 调用文件上传获取到url
List<AnnexVO> annexVOList = fileObjectUploadClient.uploadFileList(annexAddDtos).getData();
String fileId = annexVOList.get(0).getId().toString();
// 删除本地生成的文件
File qrcodeDocFile = new File("./" + timeStamp + ".pdf");
qrcodeDocFile.delete();
out.close();
return fileId;
} else {
// 其他类型直接返回文件的id
return annexVO.getId().toString();
}
}
private void downLoadFile(AnnexVO annexVO) {
// 先将远程的docx文件写到本地
URL urlfile = null;
HttpURLConnection httpUrl = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
File f = new File("./" + annexVO.getFileName());
try {
urlfile = new URL(annexVO.getAnnexUrl());
httpUrl = (HttpURLConnection) urlfile.openConnection();
httpUrl.connect();
bis = new BufferedInputStream(httpUrl.getInputStream());
bos = new BufferedOutputStream(new FileOutputStream(f));
int len = 2048;
byte[] b = new byte[len];
while ((len = bis.read(b)) != -1) {
bos.write(b, 0, len);
}
bos.flush();
bis.close();
httpUrl.disconnect();
} catch (Exception e) {
e.getLocalizedMessage();
}
}
如有问题,欢迎指正交流!