新增专家签名导出pdf

This commit is contained in:
付庆吉
2021-08-20 15:50:02 +08:00
parent 413c08ad5b
commit f6489c7062
17 changed files with 407 additions and 17 deletions

View File

@ -39,6 +39,10 @@ spec:
- name: log - name: log
hostPath: hostPath:
path: /var/lib/docker/log/349553515466-test/default-group/all #开发环境 path: /var/lib/docker/log/349553515466-test/default-group/all #开发环境
- name: storage
persistentVolumeClaim:
claimName: file-pvc
readOnly: false
# 必选Pod中容器列表 # 必选Pod中容器列表
containers: containers:
- name: biz-service-ebtp-extend - name: biz-service-ebtp-extend
@ -47,6 +51,8 @@ spec:
volumeMounts: volumeMounts:
- name: log - name: log
mountPath: /log mountPath: /log
- name: storage
mountPath: /storage
# 需要暴露的端口库号列表 # 需要暴露的端口库号列表
ports: ports:
- containerPort: 18018 - containerPort: 18018

View File

@ -39,6 +39,10 @@ spec:
- name: log - name: log
hostPath: hostPath:
path: /var/lib/docker/log/349553515466-prod/default-group/30days path: /var/lib/docker/log/349553515466-prod/default-group/30days
- name: storage
persistentVolumeClaim:
claimName: file-pvc
readOnly: false
affinity: affinity:
podAntiAffinity: podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution: requiredDuringSchedulingIgnoredDuringExecution:
@ -57,6 +61,8 @@ spec:
volumeMounts: volumeMounts:
- name: log - name: log
mountPath: /log mountPath: /log
- name: storage
mountPath: /storage
ports: ports:
- containerPort: 18018 - containerPort: 18018
livenessProbe: livenessProbe:

View File

@ -39,6 +39,10 @@ spec:
- name: log - name: log
hostPath: hostPath:
path: /var/lib/docker/log/349553515466-preprod/default-group/all #开发环境 path: /var/lib/docker/log/349553515466-preprod/default-group/all #开发环境
- name: storage
persistentVolumeClaim:
claimName: file-pvc
readOnly: false
affinity: affinity:
podAntiAffinity: podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution: requiredDuringSchedulingIgnoredDuringExecution:
@ -57,6 +61,8 @@ spec:
volumeMounts: volumeMounts:
- name: log - name: log
mountPath: /log mountPath: /log
- name: storage
mountPath: /storage
ports: ports:
- containerPort: 18018 - containerPort: 18018
resources: resources:

View File

@ -40,7 +40,10 @@ spec:
- name: log - name: log
hostPath: hostPath:
path: /var/lib/docker/log/349553515466-uat/default-group/all #开发环境 path: /var/lib/docker/log/349553515466-uat/default-group/all #开发环境
- name: storage
persistentVolumeClaim:
claimName: file-pvc
readOnly: false
# 必选Pod中容器列表 # 必选Pod中容器列表
containers: containers:
- name: biz-service-ebtp-extend - name: biz-service-ebtp-extend
@ -49,6 +52,8 @@ spec:
volumeMounts: volumeMounts:
- name: log - name: log
mountPath: /log mountPath: /log
- name: storage
mountPath: /storage
# 需要暴露的端口库号列表 # 需要暴露的端口库号列表
ports: ports:
- containerPort: 18018 - containerPort: 18018

Binary file not shown.

Binary file not shown.

27
pom.xml
View File

@ -71,6 +71,7 @@
<artifactId>commons-httpclient</artifactId> <artifactId>commons-httpclient</artifactId>
<version>3.1</version> <version>3.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>jit.vstk</groupId> <groupId>jit.vstk</groupId>
<artifactId>jit-vstk</artifactId> <artifactId>jit-vstk</artifactId>
@ -78,6 +79,21 @@
<scope>system</scope> <scope>system</scope>
<systemPath>${basedir}/lib/jit-vstk-jdk15-2.0.50-20150603.060911-1.jar</systemPath> <systemPath>${basedir}/lib/jit-vstk-jdk15-2.0.50-20150603.060911-1.jar</systemPath>
</dependency> </dependency>
<dependency>
<groupId>aspose.javadoc</groupId>
<artifactId>aspose.javadoc</artifactId>
<version>16.8.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/aspose-words-16.8.0-javadoc.jar</systemPath>
</dependency>
<dependency>
<groupId>aspose.jdk16</groupId>
<artifactId>aspose.jdk16</artifactId>
<version>16.8.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/aspose-words-16.8.0-jdk16.jar</systemPath>
</dependency>
<dependency> <dependency>
<groupId>org.apache.velocity</groupId> <groupId>org.apache.velocity</groupId>
<artifactId>velocity-tools</artifactId> <artifactId>velocity-tools</artifactId>
@ -89,7 +105,11 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc.free</artifactId>
<version>3.9.0</version>
</dependency>
</dependencies> </dependencies>
<repositories> <repositories>
@ -105,6 +125,11 @@
<updatePolicy>always</updatePolicy> <updatePolicy>always</updatePolicy>
</snapshots> </snapshots>
</repository> </repository>
<repository>
<id>com.e-iceblue</id>
<url>http://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories> </repositories>
<build> <build>

View File

@ -0,0 +1,41 @@
package com.chinaunicom.mall.ebtp.extend.signature.controller;
import com.chinaunicom.mall.ebtp.common.base.entity.BaseResponse;
import com.chinaunicom.mall.ebtp.extend.signature.entity.ExpertSignature;
import com.chinaunicom.mall.ebtp.extend.signature.service.ExpertSignatureService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
@Api(tags = "")
@RequestMapping("/v1/sign")
public class ExpertSignatureController {
@Autowired
private ExpertSignatureService expertSignatureService;
/**
* 追加专家签名
*
* @param signature
* @param request
* @param response
*/
@PreAuthorize("hasAnyAuthority('ebtp-purchase','ebtp-agency-project-manager')")
@PostMapping(value = "")
public BaseResponse<String> export(@RequestBody ExpertSignature signature, HttpServletRequest request, HttpServletResponse response) {
return BaseResponse.success(expertSignatureService.addSignature(signature));
}
}

View File

@ -0,0 +1,15 @@
package com.chinaunicom.mall.ebtp.extend.signature.entity;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class ExpertInfo {
private String expertId;
private String expertSign;
}

View File

@ -0,0 +1,18 @@
package com.chinaunicom.mall.ebtp.extend.signature.entity;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
public class ExpertSignature {
private String assessRoomId;
private String bid;
private List<ExpertInfo> experts;
}

View File

@ -0,0 +1,15 @@
package com.chinaunicom.mall.ebtp.extend.signature.service;
import com.chinaunicom.mall.ebtp.extend.signature.entity.ExpertSignature;
public interface ExpertSignatureService {
/**
* 追加专家签名
*
* @param signature
* @return
*/
String addSignature(ExpertSignature signature);
}

View File

@ -0,0 +1,228 @@
package com.chinaunicom.mall.ebtp.extend.signature.service.impl;
import cn.hutool.core.io.FileUtil;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.api.AttachmentClient;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.model.AttachmentEntity;
import com.chinaunicom.mall.ebtp.common.util.PropertyUtils;
import com.chinaunicom.mall.ebtp.extend.export.service.templateFile.TemplateFileService;
import com.chinaunicom.mall.ebtp.extend.signature.entity.ExpertSignature;
import com.chinaunicom.mall.ebtp.extend.signature.service.ExpertSignatureService;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.PictureRenderData;
import com.spire.doc.Document;
import com.spire.doc.DocumentObject;
import com.spire.doc.FileFormat;
import com.spire.doc.Section;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Decoder;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class ExpertSignatureServiceImpl implements ExpertSignatureService {
@Autowired
private AttachmentClient attachmentClient;
@Autowired
private TemplateFileService templateFileService;
@Value("${mconfig.file.upload-address}")
private String uploadAddress;
private String getUploadAddress(String assessRoomId) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
return uploadAddress + File.separator + sdf.format(System.currentTimeMillis()) + File.separator + assessRoomId + File.separator;
}
/**
* 追加专家签名
*
* @param signature
* @return
*/
@Override
public String addSignature(ExpertSignature signature) {
//获取临时存储地址
String path = this.getUploadAddress(signature.getAssessRoomId());
//获取专家签名文件
InputStream expertSign = getExpertSign(signature, path);
//获取bid的word文件
AttachmentEntity entity = attachmentClient.findByObjectId(signature.getBid()).orElse(new AttachmentEntity());
byte[] bytes = attachmentClient.downloadFileByObjectId(signature.getBid()).orElse(new byte[0]);
InputStream word = new ByteArrayInputStream(bytes);
//合并word 转为pdf
byte[] pdf = null;
try {
pdf = mergeWord(word, expertSign, path);
} catch (IOException e) {
e.printStackTrace();
}
//上传pdf到文档中心
String pdfId = PropertyUtils.getSnowflakeId();
attachmentClient.upload(pdfId, entity.getFilename(), pdf);
return pdfId;
}
/**
* 合并word
*
* @param source
* @param addObj
* @param path
* @throws IOException
*/
private byte[] mergeWord(InputStream source, InputStream addObj, String path) throws IOException {
Document d1 = new Document(source);
Document d2 = new Document(addObj);
//获取文档1的最后一节
Section lastsec = d1.getLastSection();
//遍历文档2的所有段落内容添加到文档1
for (Section section : (Iterable<Section>) d2.getSections()) {
for (DocumentObject obj : (Iterable<DocumentObject>) section.getBody().getChildObjects()
) {
lastsec.getBody().getChildObjects().add(obj.deepClone());
}
}
//保存合并后的文档
d1.saveToFile(path + "/merged.docx", FileFormat.Docx_2010);
//转为pdf
long l = System.currentTimeMillis();
if (!getLicense()) {
return null;
}
File f = new File(path + "/merged.pdf");
FileOutputStream fos = new FileOutputStream(f);
try {
com.aspose.words.Document doc = new com.aspose.words.Document(path + "/merged.docx");
doc.save(fos, SaveFormat.PDF);
} catch (Exception e) {
e.printStackTrace();
} finally {
source.close();
addObj.close();
fos.flush();
fos.close();
}
long l1 = System.currentTimeMillis();
log.info(" ======= " + (l1 - l) + " ======= ");
return IOUtils.toByteArray(new FileInputStream(f));
}
private boolean getLicense() {
boolean result = false;
InputStream is = ExpertSignatureServiceImpl.class.getClassLoader().getResourceAsStream("/license/aspose-license.xml");
// String licenseStr =
// "<License>\n" +
// " <Data>\n" +
// " <Products>\n" +
// " <Product>Aspose.Total for Java</Product>\n" +
// " <Product>Aspose.Words for Java</Product>\n" +
// " </Products>\n" +
// " <EditionType>Enterprise</EditionType>\n" +
// " <SubscriptionExpiry>20991231</SubscriptionExpiry>\n" +
// " <LicenseExpiry>20991231</LicenseExpiry>\n" +
// " <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>\n" +
// " </Data>\n" +
// " <Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>\n" +
// "</License>";
// InputStream is = null;
// is = new ByteArrayInputStream(licenseStr.getBytes(StandardCharsets.UTF_8));
License license = new License();
try {
license.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private FileInputStream getExpertSign(ExpertSignature signature, final String path) {
String imgPath = path + "/imgs/";
if (!FileUtil.exist(imgPath)) {
FileUtil.mkdir(imgPath);
}
List<PictureRenderData> pics = new ArrayList<>();
signature.getExperts().forEach(l -> {
base64ToImage(l.getExpertSign(), imgPath + l.getExpertId());
pics.add(new PictureRenderData(130, 100, imgPath + l.getExpertId()));
});
//获取签名模版
InputStream file = templateFileService.getExportTemplet("expertSignature");
//生成签名word
Map<String, Object> all = new HashMap<String, Object>() {{
put("imgs", pics);
}};
XWPFTemplate template = XWPFTemplate.compile(file).render(all);
FileInputStream fis = null;
try {
String docPath = path + "/expertSignature.docx";
template.writeToFile(docPath);
fis = new FileInputStream(new File(docPath));
} catch (IOException e) {
e.printStackTrace();
}
return fis;
}
/**
* base64字符串转换成图片
*
* @param imgStr base64字符串
* @param imgFilePath 图片存放路径
*/
private void base64ToImage(String imgStr, String imgFilePath) {
if (StringUtils.isEmpty(imgStr)) {
return;
}
BASE64Decoder decoder = new BASE64Decoder();
try {
// Base64解码
byte[] b = decoder.decodeBuffer(imgStr);
for (int i = 0; i < b.length; ++i) {
if (b[i] < 0) {// 调整异常数据
b[i] += 256;
}
}
OutputStream out = new FileOutputStream(imgFilePath);
out.write(b);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -172,9 +172,13 @@ mconfig:
tender: biz-service-ebtp-tender #投标服务 tender: biz-service-ebtp-tender #投标服务
documentcenter: core-service-document-center #文档中心 documentcenter: core-service-document-center #文档中心
usercenter: core-service-usercenter-public #用户中心 usercenter: core-service-usercenter-public #用户中心
file:
upload-address: /storage/reviewReport/
document: document:
clientHttpUrl: http://10.242.31.158:8100/auth/oauth/token?grant_type=client_credentials&client_id=bVS46ElU&client_secret=58ea04ba02475c8da2321cc99849d2a10f15b749 clientHttpUrl: http://10.242.31.158:8100/auth/oauth/token?grant_type=client_credentials&client_id=bVS46ElU&client_secret=58ea04ba02475c8da2321cc99849d2a10f15b749
# 用户暴露给 prometheus 的健康数据 # 用户暴露给 prometheus 的健康数据
management: management:
endpoints: endpoints:

View File

@ -3,18 +3,18 @@ server:
servlet: servlet:
context-path: / context-path: /
# 对应 apollo 配置中心的应用名 ## 对应 apollo 配置中心的应用名
app: #app:
id: biz-service-ebtp-extend # id: biz-service-ebtp-extend
#
# Apollo 配置信息 ## Apollo 配置信息
apollo: #apollo:
meta: http://10.242.37.148:6001/ # meta: http://10.242.37.148:6001/
bootstrap: # bootstrap:
namespace: application # namespace: application
enabled: true # enabled: true
eagerLoad: # eagerLoad:
enabled: true # enabled: true
seata: seata:
service: service:
@ -164,7 +164,8 @@ mconfig:
tender: biz-service-ebtp-tender #投标服务 tender: biz-service-ebtp-tender #投标服务
documentcenter: core-service-document-center #文档中心 documentcenter: core-service-document-center #文档中心
usercenter: core-service-usercenter-public #用户中心 usercenter: core-service-usercenter-public #用户中心
file:
upload-address: /storage/reviewReport/
document: document:
clientHttpUrl: http://10.242.31.158:8100/auth/oauth/token?grant_type=client_credentials&client_id=bVS46ElU&client_secret=58ea04ba02475c8da2321cc99849d2a10f15b749 clientHttpUrl: http://10.242.31.158:8100/auth/oauth/token?grant_type=client_credentials&client_id=bVS46ElU&client_secret=58ea04ba02475c8da2321cc99849d2a10f15b749

View File

@ -167,6 +167,8 @@ mconfig:
tender: biz-service-ebtp-tender #投标服务 tender: biz-service-ebtp-tender #投标服务
documentcenter: core-service-document-center #文档中心 documentcenter: core-service-document-center #文档中心
usercenter: core-service-usercenter-public #用户中心 usercenter: core-service-usercenter-public #用户中心
file:
upload-address: /storage/reviewReport/
document: document:
clientHttpUrl: http://10.238.25.112:8100/auth/oauth/token?grant_type=client_credentials&client_id=bVS46ElU&client_secret=58ea04ba02475c8da2321cc99849d2a10f15b749 clientHttpUrl: http://10.238.25.112:8100/auth/oauth/token?grant_type=client_credentials&client_id=bVS46ElU&client_secret=58ea04ba02475c8da2321cc99849d2a10f15b749

View File

@ -167,6 +167,8 @@ mconfig:
tender: biz-service-ebtp-tender #投标服务 tender: biz-service-ebtp-tender #投标服务
documentcenter: core-service-document-center #文档中心 documentcenter: core-service-document-center #文档中心
usercenter: core-service-usercenter-public #用户中心 usercenter: core-service-usercenter-public #用户中心
file:
upload-address: /storage/reviewReport/
document: document:
clientHttpUrl: http://10.242.31.158:8100/auth/oauth/token?grant_type=client_credentials&client_id=bVS46ElU&client_secret=58ea04ba02475c8da2321cc99849d2a10f15b749 clientHttpUrl: http://10.242.31.158:8100/auth/oauth/token?grant_type=client_credentials&client_id=bVS46ElU&client_secret=58ea04ba02475c8da2321cc99849d2a10f15b749

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Words for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
</Data>
<Signature>
sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=
</Signature>
</License>