|
@@ -5,10 +5,20 @@ import lombok.AllArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
|
|
import org.apache.pdfbox.pdmodel.PDPage;
|
|
|
+import org.jsoup.Jsoup;
|
|
|
+import org.jsoup.nodes.Document;
|
|
|
+import org.jsoup.nodes.Element;
|
|
|
+import org.jsoup.select.Elements;
|
|
|
import org.springblade.business.vo.TaskSignInfoVO;
|
|
|
+import org.springblade.common.utils.SnowFlakeUtil;
|
|
|
+import org.springblade.core.oss.model.BladeFile;
|
|
|
+import org.springblade.core.tool.utils.Func;
|
|
|
+import org.springblade.core.tool.utils.IoUtil;
|
|
|
import org.springblade.evisa.service.EVDataService;
|
|
|
import org.springblade.evisa.utils.FileUtils;
|
|
|
+import org.springblade.evisa.vo.ArchivesSplitInfoVO;
|
|
|
import org.springblade.evisa.vo.TaskArchiveSplitVO;
|
|
|
+import org.springblade.resource.feign.NewIOSSClient;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
|
@@ -17,8 +27,7 @@ import org.springframework.scheduling.annotation.Scheduled;
|
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
-import java.io.File;
|
|
|
-import java.io.InputStream;
|
|
|
+import java.io.*;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.concurrent.CompletableFuture;
|
|
@@ -26,6 +35,7 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
import org.apache.pdfbox.rendering.PDFRenderer;
|
|
|
+
|
|
|
import java.awt.image.BufferedImage;
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
|
@@ -47,34 +57,32 @@ public class ArchiveController {
|
|
|
// jdbc
|
|
|
private final JdbcTemplate jdbcTemplate;
|
|
|
|
|
|
- //电签服务类
|
|
|
- private final EVDataService evDataService;
|
|
|
+ private final NewIOSSClient newIOSSClient;
|
|
|
|
|
|
// 线程池
|
|
|
@Resource(name = "taskExecutor1")
|
|
|
private ThreadPoolExecutor executor;
|
|
|
|
|
|
- @Scheduled(cron = "0/10 * * * * ?")
|
|
|
+ @Scheduled(cron = "0 0/1 * * * ?")
|
|
|
public void SignInfo() {
|
|
|
//执行代码
|
|
|
|
|
|
- log.info("扫描开始");
|
|
|
-
|
|
|
- String sql = "SELECT a.id,a.archive_id as archiveId,a.file_url as fileUrl from u_archive_file a, u_task_split b where FIND_IN_SET(a.archive_id,b.ids) and b.type=3 ";
|
|
|
+ log.info("分解pdf专图片");
|
|
|
+ String sql = "SELECT distinct b.id,b.archive_id as archiveId ,b.file_url as fileUrl,c.id as taskId from u_archives_auto a , u_archive_file b ,u_task_split c where a.id=b.archive_id and ((FIND_IN_SET(a.id,c.ids) and c.type=3) or (a.contract_id=c.contract_id and c.type=2)) and a.is_deleted=0 and b.is_deleted=0 and a.split_status not in(1,2) ";
|
|
|
List<TaskArchiveSplitVO> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TaskArchiveSplitVO.class));
|
|
|
|
|
|
if (query != null && query.size() >= 1) {
|
|
|
for (TaskArchiveSplitVO dataInfo : query) {
|
|
|
if (executor.getQueue().size() <= 10) {
|
|
|
- Boolean aBoolean = RedisTemplate.hasKey("sign-" + dataInfo.getArchiveId());
|
|
|
+ Boolean aBoolean = RedisTemplate.hasKey("splitpng-" + dataInfo.getArchiveId());
|
|
|
if (!aBoolean) {
|
|
|
|
|
|
- if(!aBoolean){
|
|
|
- RedisTemplate.opsForValue().set("sign-" + dataInfo.getArchiveId(), "1", 7200, TimeUnit.SECONDS);
|
|
|
+ if (!aBoolean) {
|
|
|
+ RedisTemplate.opsForValue().set("splitpng-" + dataInfo.getArchiveId(), "1", 7200, TimeUnit.SECONDS);
|
|
|
CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
|
|
|
try {
|
|
|
/*===============执行批量任务===============*/
|
|
|
- signTaskBatch(dataInfo);
|
|
|
+ signTaskBatchpngToHtml(dataInfo);
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
@@ -84,31 +92,217 @@ public class ArchiveController {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- System.out.println("队列数量" + executor.getQueue().size());
|
|
|
- System.out.println("活跃数量" + executor.getActiveCount());
|
|
|
- System.out.println("总共数量" + executor.getTaskCount());
|
|
|
- System.out.println("完成数量" + executor.getCompletedTaskCount());
|
|
|
+ System.out.println("队列数量_图片" + executor.getQueue().size());
|
|
|
+ System.out.println("活跃数量_图片" + executor.getActiveCount());
|
|
|
+ System.out.println("总共数量_图片" + executor.getTaskCount());
|
|
|
+ System.out.println("完成数量_图片" + executor.getCompletedTaskCount());
|
|
|
}
|
|
|
|
|
|
- public void signTaskBatch(TaskArchiveSplitVO taskSign) {
|
|
|
+ // 分解第一页的任务
|
|
|
+ public void signTaskBatchpngToHtml(TaskArchiveSplitVO taskSign) {
|
|
|
try {
|
|
|
String fileUrl = taskSign.getFileUrl();
|
|
|
String archiveId = taskSign.getArchiveId();
|
|
|
String id = taskSign.getId();
|
|
|
- // 获取pdf第一页的数据
|
|
|
- String firstUrl = FileUtils.getSysLocalFileUrl()+"archiveSplit/"+archiveId+"_001.pdf";
|
|
|
- getPdfByPage(2,2,fileUrl,firstUrl);
|
|
|
+ String taskId = taskSign.getTaskId();
|
|
|
+
|
|
|
+ // 获取pdf第二页的数据
|
|
|
+ String firstUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_001.pdf";
|
|
|
+ File file = new File(firstUrl);
|
|
|
+ if (!file.exists()) {
|
|
|
+ getPdfByPage(2, 2, fileUrl, firstUrl);
|
|
|
+ }
|
|
|
+
|
|
|
// 保存第一页为300DPI图片
|
|
|
String imagePath = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_001.png";
|
|
|
- savePdfAsImage(1, firstUrl, imagePath);
|
|
|
+ File imgfile = new File(imagePath);
|
|
|
+ if (!imgfile.exists()) {
|
|
|
+ savePdfAsImage(1, firstUrl, imagePath);
|
|
|
+ }
|
|
|
|
|
|
+ //判断
|
|
|
+ List<Map<String, Object>> mapList = jdbcTemplate.queryForList("select * from u_archives_split_info where id=" + id + "");
|
|
|
+ if (mapList != null && Func.isNotEmpty(mapList) && mapList.size() >= 1) {
|
|
|
+ String status = mapList.get(0).get("status") + "";
|
|
|
+ if (status.equals("3")) {
|
|
|
+ String updateSql = "update u_archives_auto set split_status=1 where id=" + id;
|
|
|
+ jdbcTemplate.execute(updateSql);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ String sql22 = "insert into u_archives_split_info(id,status,file_url,first_file_url,task_id,archive_id,create_time) VALUES(" + id + ",2,'" + fileUrl + "','" + imagePath + "'," + taskId + "," + archiveId + ",SYSDATE())";
|
|
|
+ jdbcTemplate.execute(sql22);
|
|
|
+ String updateSql = "update u_archives_auto set split_status=2 where id=" + id;
|
|
|
+ jdbcTemplate.execute(updateSql);
|
|
|
+ }
|
|
|
+ RedisTemplate.delete("splitpng-" + archiveId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Scheduled(cron = "0/30 * * * * ?")
|
|
|
+ public void SplitPdfInfo() {
|
|
|
+ //执行代码
|
|
|
+
|
|
|
+ log.info("分解html开始");
|
|
|
+ String sql = "select * from u_archives_split_info where status =2 "; // and TIMESTAMPDIFF(MINUTE, create_time, NOW()) >=3";
|
|
|
+ List<ArchivesSplitInfoVO> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ArchivesSplitInfoVO.class));
|
|
|
+
|
|
|
+ if (query != null && query.size() >= 1) {
|
|
|
+ for (ArchivesSplitInfoVO dataInfo : query) {
|
|
|
+ if (executor.getQueue().size() <= 10) {
|
|
|
+ Boolean aBoolean = RedisTemplate.hasKey("splithtml-" + dataInfo.getArchiveId());
|
|
|
+ if (!aBoolean) {
|
|
|
+
|
|
|
+ if (!aBoolean) {
|
|
|
+ RedisTemplate.opsForValue().set("splithtml-" + dataInfo.getArchiveId(), "1", 600, TimeUnit.SECONDS);
|
|
|
+ CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
|
|
|
+ try {
|
|
|
+ /*===============执行批量任务===============*/
|
|
|
+ signTaskBatchpng(dataInfo);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }, executor);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ System.out.println("队列数量_html" + executor.getQueue().size());
|
|
|
+ System.out.println("活跃数量_html" + executor.getActiveCount());
|
|
|
+ System.out.println("总共数量_html" + executor.getTaskCount());
|
|
|
+ System.out.println("完成数量_html" + executor.getCompletedTaskCount());
|
|
|
+ }
|
|
|
+
|
|
|
+ public void signTaskBatchpng(ArchivesSplitInfoVO taskSign) {
|
|
|
+ try {
|
|
|
+ String archiveId = taskSign.getArchiveId();
|
|
|
+ String fileUlr = taskSign.getFileUrl();
|
|
|
+ String firstPage = FileUtils.getSysLocalFileUrl() + "archiveSplit/";
|
|
|
+ int bkb = 0 ;
|
|
|
+ //将imagePath 的数据转成一个可解析的html
|
|
|
+ String htmlUrl1 = pngToHtml(firstPage, archiveId);
|
|
|
+ String htmlUrl2 = pngToHtml(firstPage, archiveId);
|
|
|
+ String htmlUrl = "";
|
|
|
+ if (htmlUrl1.equals(htmlUrl2) && htmlUrl1.indexOf("_001.html") >= 0 && htmlUrl1.indexOf("archiveSplit") >= 0) {
|
|
|
+ htmlUrl = htmlUrl2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (htmlUrl.indexOf("_001.html") >= 0 && htmlUrl.indexOf("archiveSplit") >= 0) {
|
|
|
+ String htmlString = IoUtil.readToString(new FileInputStream(htmlUrl));
|
|
|
+ Document doc = Jsoup.parse(htmlString);
|
|
|
+ Element table = doc.select("table").first();
|
|
|
+ Elements trs = table.select("tr");
|
|
|
+
|
|
|
+ for (int i = 1; i <= trs.size() - 1; i++) {
|
|
|
+ Element tr = trs.get(i);
|
|
|
+ String zrz = tr.select("td").get(0).text();
|
|
|
+ String wjtm = tr.select("td").get(1).text();
|
|
|
+ String rq = tr.select("td").get(2).text();
|
|
|
+ String ym = tr.select("td").get(3).text();
|
|
|
+ int startYm = 0;
|
|
|
+ int endYm = 0;
|
|
|
+ if(i<trs.size()-1){
|
|
|
+ startYm = Func.toInt(ym);
|
|
|
+ String enData = trs.get(i+1).select("td").get(3).text();
|
|
|
+ if(enData.indexOf("-")>=0){
|
|
|
+ endYm = Func.toInt(enData.split("-")[0])-1;
|
|
|
+ }else{
|
|
|
+ endYm = Func.toInt(enData)-1;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if(ym.indexOf("-")>=0){
|
|
|
+ String[] split = ym.split("-");
|
|
|
+ startYm = Func.toInt(split[0]);
|
|
|
+ endYm = Func.toInt(split[1]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ startYm = startYm + 2 ;
|
|
|
+ endYm = endYm + 2 ;
|
|
|
+ System.out.println(zrz + " " + wjtm + " " + rq + " " + ym);
|
|
|
+ // 分解文件
|
|
|
+ String fmlUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/"+archiveId+"_cf_00"+i+".pdf";
|
|
|
+ getPdfByPage(startYm,endYm,fileUlr,fmlUrl);
|
|
|
+ saveDataToMysql(fmlUrl,wjtm,taskSign.getId(),endYm-startYm+1);
|
|
|
+ bkb = endYm ;
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加封面信息
|
|
|
+ String fmlUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/"+archiveId+"_fm_001.pdf";
|
|
|
+ getPdfByPage(1,1,fileUlr,fmlUrl);
|
|
|
+ saveDataToMysql(fmlUrl,"封面",taskSign.getId(),1);
|
|
|
+
|
|
|
+ // 卷内目录
|
|
|
+ String jnmuUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/"+archiveId+"_jnml_001.pdf";
|
|
|
+ getPdfByPage(2,2,fileUlr,jnmuUrl);
|
|
|
+ saveDataToMysql(jnmuUrl,"卷内目录",taskSign.getId(),1);
|
|
|
+
|
|
|
+ // 卷内备考表
|
|
|
+ String jnbkbUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/"+archiveId+"_jnbkb_001.pdf";
|
|
|
+ getPdfByPage(bkb+1,bkb+1,fileUlr,jnbkbUrl);
|
|
|
+ saveDataToMysql(jnbkbUrl,"卷内备考表",taskSign.getId(),1);
|
|
|
+
|
|
|
+ // 修改任务状态
|
|
|
+ String updateSql = "update u_archives_split_info set status=3 where id=" + taskSign.getId();
|
|
|
+ jdbcTemplate.execute(updateSql);
|
|
|
+ // 修改 u_archives_auto 为 已经分解
|
|
|
+ String updateSqlAuto = "update u_archives_auto set split_status=1 where id=" + taskSign.getArchiveId();
|
|
|
+ jdbcTemplate.execute(updateSqlAuto);
|
|
|
+
|
|
|
+ // 统计各个任务的结果
|
|
|
+ String taxkSql = "UPDATE u_task_split a set finished = (SELECT count(1) from u_archives_auto b where FIND_IN_SET(b.id,a.ids) and b.split_status=1) where FIND_IN_SET("+taskSign.getArchiveId()+",a.ids) and a.type=3";
|
|
|
+ String taxkSql2 = "UPDATE u_task_split a set finished = (SELECT count(1) from u_archives_auto b where a.contract_id=b.contract_id) where a.id="+taskSign.getTaskId()+" and a.type=2";
|
|
|
+ jdbcTemplate.execute(taxkSql);
|
|
|
+ jdbcTemplate.execute(taxkSql2);
|
|
|
+
|
|
|
+ // 修改完成情况
|
|
|
+
|
|
|
+ RedisTemplate.delete("splithtml-" + archiveId);
|
|
|
} catch (Exception e) {
|
|
|
throw new RuntimeException(e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void getPdfByPage(int startPage, int endPage, String filePath, String savePath) {
|
|
|
+ public static String pngToHtml(String fileUrl, String pKeyId) {
|
|
|
+ String lasHhtmlUrl = "";
|
|
|
+ try {
|
|
|
+ // 定义Python解释器路径和脚本路径
|
|
|
+ String pythonScript = "/Users/hongchuangyanfa/Desktop/PycharmProjects/splitPngToHtml.py";
|
|
|
+ // 构建命令
|
|
|
+ ProcessBuilder pb = new ProcessBuilder("python3", pythonScript, fileUrl, pKeyId);
|
|
|
+ Process process = pb.start();
|
|
|
+
|
|
|
+ // 读取Python脚本输出
|
|
|
+ BufferedReader reader = new BufferedReader(
|
|
|
+ new InputStreamReader(process.getInputStream()));
|
|
|
+ String htmlUrl;
|
|
|
+ while ((htmlUrl = reader.readLine()) != null) {
|
|
|
+ System.out.println("222" + htmlUrl);
|
|
|
+ if (htmlUrl.indexOf("html文件路径") >= 0 && htmlUrl.indexOf("_001.html") >= 0 && htmlUrl.indexOf("archiveSplit") >= 0) {
|
|
|
+ lasHhtmlUrl = htmlUrl.replace("html文件路径", "");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 等待进程结束
|
|
|
+ int exitCode = process.waitFor();
|
|
|
+ if (exitCode == 0) {
|
|
|
+ return lasHhtmlUrl;
|
|
|
+ } else {
|
|
|
+ return "1";
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ return "1";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public static void getPdfByPage(int startPage, int endPage, String filePath, String savePath) {
|
|
|
try {
|
|
|
InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(filePath);
|
|
|
// 加载PDF文件
|
|
@@ -152,18 +346,51 @@ public class ArchiveController {
|
|
|
final int DPI = 300;
|
|
|
|
|
|
// 渲染指定页面(注意PDFBox使用0-based索引)
|
|
|
- BufferedImage image = renderer.renderImage(pageNum - 1, DPI / 72f);
|
|
|
-
|
|
|
+ //BufferedImage image = renderer.renderImage(pageNum - 1, DPI / 72f);
|
|
|
+ BufferedImage image = renderer.renderImageWithDPI(0, DPI); // 0 表示第一页
|
|
|
// 确保输出目录存在
|
|
|
File outputFile = new File(outputPath);
|
|
|
outputFile.getParentFile().mkdirs();
|
|
|
|
|
|
// 保存为PNG格式(可改为JPG等)
|
|
|
ImageIO.write(image, "PNG", outputFile);
|
|
|
+
|
|
|
log.info("PDF页面已成功保存为图片: {}", outputPath);
|
|
|
+ inputStream.close();
|
|
|
+ document.close();
|
|
|
} catch (Exception e) {
|
|
|
log.error("PDF转图片失败", e);
|
|
|
throw new RuntimeException("PDF转图片失败", e);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ public int saveDataToMysql(String upFileUrl,String fileName,String fileId,int filePage) {
|
|
|
+ // 获取封面信息
|
|
|
+ long newPkId = SnowFlakeUtil.getId(); //主键Id
|
|
|
+ File fmfile = new File(upFileUrl);
|
|
|
+ if (fmfile.exists()) {
|
|
|
+ BladeFile bladeFile = this.newIOSSClient.uploadFile(fileName+".pdf", upFileUrl);
|
|
|
+ if (bladeFile != null && Func.isNotEmpty(bladeFile.getLink())) {
|
|
|
+ String FmPdfUrl = bladeFile.getLink();
|
|
|
+ String sql = " insert into u_archive_file( " +
|
|
|
+ " id,project_id,contract_id,node_id,file_number,file_name,file_time,file_url,pdf_file_url,file_page,is_approval,is_certification,is_need_certification,duty_user,create_user,create_dept,create_time,update_user,update_time,status,is_deleted,sheet_type,sheet_source, " +
|
|
|
+ " drawing_no,cite_change_number,certification_time,e_visa_file,node_ext_id,file_type,archive_id,origin_id,filming_time,filmingor_time,tag_id,pic_code,refer_code,film_code,width,height,ftime,utime,del_time,sort,box_name,box_number,is_auto_file,is_archive,page_num, " +
|
|
|
+ " file_size,source_type,is_element,pdf_page_url,fid,rectification,classify,m_wbs_tree_contract_p_key_id,u_image_classification_file_id,archive_file_storage_type,node_tree_structure,date_name,archive_file_stroage_type,out_id,sort_num " +
|
|
|
+ " ) " +
|
|
|
+ " SELECT "+newPkId+",project_id,contract_id,node_id,file_number,'" + fileName + "',file_time,'" + FmPdfUrl + "','" + FmPdfUrl + "',"+filePage+",is_approval,is_certification,is_need_certification,duty_user,create_user,create_dept,create_time,update_user,update_time,status,is_deleted,sheet_type,sheet_source, " +
|
|
|
+ " drawing_no,cite_change_number,certification_time,e_visa_file,node_ext_id,file_type,archive_id,origin_id,filming_time,filmingor_time,tag_id,pic_code,refer_code,film_code,width,height,ftime,utime,del_time,sort,box_name,box_number,is_auto_file,is_archive,page_num, " +
|
|
|
+ " file_size,source_type,is_element,pdf_page_url,fid,rectification,classify,m_wbs_tree_contract_p_key_id,u_image_classification_file_id,archive_file_storage_type,node_tree_structure,date_name,archive_file_stroage_type,out_id,sort_num " +
|
|
|
+ " from u_archive_file where id=" + fileId;
|
|
|
+ System.out.println(fileName + "----" + sql);
|
|
|
+ jdbcTemplate.execute(sql);
|
|
|
+ return 200;
|
|
|
+ } else {
|
|
|
+ // 检查一下oss是否启动
|
|
|
+ System.out.println("oss服务未启动,无法上传文件到oss");
|
|
|
+ return 500;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ return 404;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|