차세대세외수입 고지서 pdf파일 정보 추출 관련 controller, html 추가

1. 요청처리용 컨트롤러 추가
2. 업로드용 html화면 추가
main
이범준 10 months ago
parent e812d2bbed
commit 4ae3a2e631

@ -7,6 +7,8 @@ import java.io.OutputStream;
import java.io.StringWriter; import java.io.StringWriter;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@ -22,10 +24,13 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource; import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamResult;
import org.apache.commons.io.FilenameUtils;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
@ -194,5 +199,36 @@ public class FileController extends cokr.xit.base.file.web.FileController {
} }
} }
@PostMapping(name = "처리 전 파일업로드", value = "/uploadBeforeProcess.do")
public ModelAndView uploadBeforeProcess(MultipartFile[] uploadFiles) {
ModelAndView mav = new ModelAndView("jsonView");
boolean saved = false;
MultipartFile uploadFile = uploadFiles[0];
String orginalFileName = uploadFile.getOriginalFilename();
String extension = FilenameUtils.getExtension(orginalFileName);
SimpleDateFormat ymdhmsFormat = new SimpleDateFormat("yyyyMMddHHmmss");
String currentTime = ymdhmsFormat.format(new Date());
String folderPath = "files/tempForProcess";
File folder = new File(folderPath);
folder.mkdirs();
String filePath = folderPath + "/"+currentTime+"."+extension;
File file = new File(filePath);
try {
uploadFile.transferTo(file);
saved = true;
} catch (IOException e) {
e.printStackTrace();
}
mav.addObject("saved", saved);
mav.addObject("filePath", filePath);
return mav;
}
} }

@ -1,15 +1,49 @@
package cokr.xit.fims.cmmn.pdf; package cokr.xit.fims.cmmn.pdf;
import java.awt.geom.Rectangle2D;
import java.io.IOException; import java.io.IOException;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.text.PDFTextStripper; import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.pdfbox.text.PDFTextStripperByArea;
public class ExtractText { public class ExtractText {
public static final String REGEXP_PATTERN_NUMBER = "^[\\d]*$"; public static final String REGEXP_PATTERN_NUMBER = "^[\\d]*$";
public static String getExtractByStng(PDDocument document, int pageNum,
float x, float y, float w, float h) {
try {
PDFTextStripperByArea textStripper = new PDFTextStripperByArea();
Rectangle2D rect = new java.awt.geom.Rectangle2D.Float(x, y, w, h);
textStripper.addRegion("region", rect);
PDPage docPage = document.getPage(pageNum-1);
textStripper.extractRegions(docPage);
String textForRegion = textStripper.getTextForRegion("region");
System.out.println("영역지정으로 추출된 텍스트");
System.out.println(textForRegion);
return textForRegion;
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
public static String getExtractEpayNo(PDDocument pdDocument, int pageNum) { public static String getExtractEpayNo(PDDocument pdDocument, int pageNum) {
String epayNo = ""; String epayNo = "";

@ -1,7 +1,6 @@
package cokr.xit.fims.cmmn.pdf; package cokr.xit.fims.cmmn.pdf;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -10,7 +9,6 @@ import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageTree; import org.apache.pdfbox.pdmodel.PDPageTree;
import org.springframework.util.ResourceUtils;
public class PDFUtil { public class PDFUtil {
@ -20,8 +18,8 @@ public class PDFUtil {
File file = null; File file = null;
try { try {
file = ResourceUtils.getFile("classpath:sample/"+pdfName); file = new File(pdfName);
} catch (FileNotFoundException e2) { } catch (Exception e2) {
e2.printStackTrace(); e2.printStackTrace();
} }
PDDocument pdDocument = null; PDDocument pdDocument = null;
@ -44,7 +42,7 @@ public class PDFUtil {
extraction = new Extraction(); extraction = new Extraction();
extraction.setPage(pageIndex+1); extraction.setPage(pageIndex+1);
String epayNo = ExtractText.getExtractEpayNo(pdDocument, pageIndex+1); String epayNo = ExtractText.getExtractByStng(pdDocument, pageIndex+1, 0 , 0, 100, 100);
extraction.setEpayNo(epayNo); extraction.setEpayNo(epayNo);

@ -0,0 +1,34 @@
package cokr.xit.fims.cmmn.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import cokr.xit.fims.cmmn.pdf.PDFUtil;
import cokr.xit.foundation.web.AbstractController;
@Controller
@RequestMapping(name = "연계 처리", value = "/link")
public class LinkController extends AbstractController {
@RequestMapping(name = "파일 처리", value = "/fileProcess.do")
public ModelAndView fileProcess(String filePath, String job, String param) {
ModelAndView mav = new ModelAndView("jsonView");
boolean saved = false;
System.out.println("파일경로 : " +filePath);
System.out.println("업무 : " + job);
System.out.println("파라미터 : "+ param);
//차세대 세외수입 pdf파일 정보 추출
if(job.equals("01")) {
PDFUtil.extract(param);
}
mav.addObject("saved", saved);
return mav;
}
}

@ -34,17 +34,26 @@
</div> </div>
<div class="me-1" style="min-width: max-content;"> <div class="me-1" style="min-width: max-content;">
<div class="form-check-inline custom-option custom-option-basic me-1" style="background-color: #d9dee3"> <div class="form-check-inline custom-option custom-option-basic me-1" style="background-color: #d9dee3">
<label for="securityMode--top" class="form-check-label custom-option-content"> <label for="securityMode--top" class="form-check-label custom-option-content d-flex justify-content-center">
<input type="checkbox" id="securityMode--top" name="securityMode" class="form-check-input" value="Y" /> <input type="checkbox" id="securityMode--top" name="securityMode"
보안모드 class="form-check-input me-1 align-self-center" value="Y" />
<span class="text-center">
보안모드<br/>(F9)
</span>
</label> </label>
</div> </div>
<div class="form-check-inline custom-option custom-option-basic me-1" style="background-color: #d9dee3"> <div class="form-check-inline custom-option custom-option-basic me-1" style="background-color: #d9dee3">
<label for="photoMask--top" class="form-check-label custom-option-content"> <label for="photoMask--top" class="form-check-label custom-option-content d-flex justify-content-center">
<input type="checkbox" id="photoMask--top" name="photoMask" class="form-check-input" value="Y" checked /> <input type="checkbox" id="photoMask--top" name="photoMask"
단속사진 모자이크 class="form-check-input me-1 align-self-center" value="Y" checked />
<span class="text-center">
단속사진 모자이크<br/>(F10)
</span>
</label> </label>
</div> </div>
<button type="button" id="btnOpenTempFileUploadWindow" class="btn btn-outline-dark">
외부자료 파일 처리
</button>
<button type="button" id="btnGoToCvlcptDscsn" class="btn btn-outline-dark"> <button type="button" id="btnGoToCvlcptDscsn" class="btn btn-outline-dark">
종합민원관리 종합민원관리
</button> </button>
@ -154,6 +163,14 @@
</nav> </nav>
<c:set var="topScript" scope="request"> <c:set var="topScript" scope="request">
function fnOpenTempFileUploadWindow(){
window.open(
wctx.url("/resources/html/fileUpload.html")
,"fileUpload"
,'top=10, left=10, width=1000, height=500'
);
}
function fnOpenMyInfo(){ function fnOpenMyInfo(){
window.open( window.open(
wctx.url("/user/openMyInfo.do") wctx.url("/user/openMyInfo.do")
@ -368,5 +385,10 @@ $("#photoMask--top").on( "click", function() {
fn_photoMask(false); fn_photoMask(false);
} }
}); });
/*--------------------- 외부자료 파일 처리 ---------------------*/
$("#btnOpenTempFileUploadWindow").on( "click", function() {
fnOpenTempFileUploadWindow();
});
</c:set> </c:set>

@ -0,0 +1,266 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="/resources/image/favicon.ico" />
<!-- Fonts -->
<link rel="stylesheet" href="/resources/font/publicsans/fontface.css" />
<!-- Icons. Uncomment required icon fonts -->
<link rel="stylesheet" href="/resources/3rd-party/sneat/fonts/boxicons.css" />
<link rel="stylesheet" href="/resources/3rd-party/sneat/fonts/fontawesome.css" />
<link rel="stylesheet" href="/resources/3rd-party/sneat/fonts/flag-icons.css" />
<link rel="stylesheet" href="/resources/css/fims/framework/common/xit-icon.css" />
<!-- Core CSS -->
<link rel="stylesheet" href="/resources/css/fims/framework/common/xit-core.css" />
<link rel="stylesheet" href="/resources/3rd-party/sneat/css/theme-default.css" />
<link rel="stylesheet" href="/resources/3rd-party/sneat/css/docs.css" />
<link rel="stylesheet" href="/resources/css/fims/framework/common/xit-core-extend.css" />
<!-- Vendors CSS -->
<link rel="stylesheet" href="/resources/3rd-party/sneat/libs/perfect-scrollbar/perfect-scrollbar.css" />
<link rel="stylesheet" href="/resources/3rd-party/sneat/libs/bs-stepper/bs-stepper.css" />
<link rel="stylesheet" href="/resources/css/styles.css" />
<link rel="stylesheet" href="/resources/css/fims/framework/common/common.css"/>
<link rel="stylesheet" href="/resources/lib/fims/framework/jquery-ui/1.13.2/themes/redmond/jquery-ui.css" />
<link rel="stylesheet" href="/resources/lib/fims/framework/datepicker/datepicker.css" />
<title>파일업로드</title>
</head>
<body>
<div class="card m-4 p-3">
<form id="hiddenForm" name="hiddenForm">
<input type="hidden" id="filePath" name="filePath" />
</form>
<div class="bs-stepper wizard-numbered mt-2"> <!-- 스테퍼 -->
<div class="bs-stepper-header"> <!-- 스텝헤더s -->
<div class="step" data-target="#uploadStep"> <!-- 스텝헤더1 -->
<button type="button" class="step-trigger" disabled>
<span class="bs-stepper-circle">1</span>
<span class="bs-stepper-label mt-1">
<span class="bs-stepper-title">파일업로드</span>
<span class="bs-stepper-subtitle">파일업로드</span>
</span>
</button>
</div>
<div class="line">
<i class="bx bx-chevron-right"></i>
</div>
<div class="step" data-target="#selectJobStep"> <!-- 스텝헤더2 -->
<button type="button" class="step-trigger" disabled>
<span class="bs-stepper-circle">2</span>
<span class="bs-stepper-label mt-1">
<span class="bs-stepper-title">처리업무 선택</span>
<span class="bs-stepper-subtitle">처리업무 선택</span>
</span>
</button>
</div>
<div class="line">
<i class="bx bx-chevron-right"></i>
</div>
<div class="step" data-target="#additionalStep"> <!-- 스텝헤더3 -->
<button type="button" class="step-trigger" disabled>
<span class="bs-stepper-circle">3</span>
<span class="bs-stepper-label mt-1">
<span class="bs-stepper-title">추가작업</span>
<span class="bs-stepper-subtitle">추가작업</span>
</span>
</button>
</div>
</div> <!-- 스텝헤더s끝 -->
<div class="bs-stepper-content"> <!-- 스텝콘텐츠 -->
<div id="uploadStep" class="content"> <!-- 스텝콘텐츠1 -->
<form name="form1" id="form1" method="post" enctype="multipart/form-data">
<label>파일</label>
<input type="file" id="uploadFiles" name="uploadFiles" />
</form>
<div class="col-12 d-flex justify-content-between">
<button type="button" class="btn btn-primary ms-auto" onclick="fnTempFileUpload();">전송</button>
</div>
</div>
<div id="selectJobStep" class="content"> <!-- 스텝콘텐츠2 -->
<form name="form2" id="form2">
<label class="required">처리 업무</label>
<select id="selectJob" name="selectJob" class="form-select" style="max-width:300px!important;">
<option value="">선택하세요.</option>
<option value="01">차세대세외수입 고지서 pdf 정보 추출</option>
</select>
</form>
<div class="col-12 d-flex justify-content-between">
<button type="button" id="btnSelectJob" class="btn btn-primary ms-auto">
<span class="align-middle d-sm-inline-block d-none me-sm-1 me-0">Next</span>
<i class="bx bx-chevron-right bx-sm me-sm-n2"></i>
</button>
</div>
</div>
<div id="additionalStep" class="content"> <!-- 스텝콘텐츠3 -->
<form name="form3" id="form3">
<label>서식</label>
<select id="tmplatId" name="tmplatId" class="form-select">
<option value="JU001">사전통지서</option>
<option value="JU002">본고지(수신분)</option>
</select>
</form>
<div class="col-12 d-flex justify-content-between">
<button type="button" id="btnComplete"
class="btn btn-success ms-auto">완료</button>
</div>
</div>
</div>
</div>
</div>
<script type="text/JavaScript" src="/resources/3rd-party/sneat/libs/jquery/jquery.js" ></script>
<script src="/resources/3rd-party/sneat/libs/popper/popper.js"></script>
<script src="/resources/3rd-party/sneat/js/bootstrap.js"></script>
<script src="/resources/3rd-party/sneat/libs/bs-stepper/bs-stepper.js"></script>
<script src="/resources/3rd-party/sneat/libs/perfect-scrollbar/perfect-scrollbar.js"></script>
<script src="/resources/3rd-party/sneat/libs/hammer/hammer.js"></script>
<script src="/resources/3rd-party/sneat/libs/i18n/i18n.js"></script>
<script src="/resources/3rd-party/sneat/js/menu.js"></script>
<script src="/resources/3rd-party/sneat/libs/jstree/jstree.js"></script>
<script src="/resources/3rd-party/jstree/jstree-support.js"></script>
<script src="/resources/3rd-party/sneat/libs/chartjs/chartjs.js"></script>
<script src="/resources/lib/fims/framework/jquery-ui/1.13.2/jquery-ui.js"></script>
<script src="/resources/js/base/base.js"></script>
<script src="/resources/js/base/base-fims.js"></script>
<script src="/resources/js/base/dataset.js"></script>
<script language="javascript">
const wizardNumbered = document.querySelector(".wizard-numbered");
const numberedStepper = new Stepper(wizardNumbered, {
linear: false
});
if (typeof wizardNumbered !== undefined && wizardNumbered !== null) {
const wizardNumberedBtnNextList = [].slice.call(wizardNumbered.querySelectorAll('.btn-next'));
const wizardNumberedBtnPrevList = [].slice.call(wizardNumbered.querySelectorAll('.btn-prev'));
const wizardNumberedBtnSubmit = wizardNumbered.querySelector('.btn-submit');
if (wizardNumberedBtnNextList) {
wizardNumberedBtnNextList.forEach(wizardNumberedBtnNext => {
wizardNumberedBtnNext.addEventListener('click', event => {
numberedStepper.next();
});
});
}
if (wizardNumberedBtnPrevList) {
wizardNumberedBtnPrevList.forEach(wizardNumberedBtnPrev => {
wizardNumberedBtnPrev.addEventListener('click', event => {
numberedStepper.previous();
});
});
}
if (wizardNumberedBtnSubmit) {
wizardNumberedBtnSubmit.addEventListener('click', event => {
});
}
}
function fnTempFileUpload(){
var formData = new FormData(document.getElementById("form1"));
ajax.post({
url : wctx.url("/file/uploadBeforeProcess.do"),
contentType : false, processData : false,
data : formData,
success : (resp) => {
if(resp.saved){
$("#filePath").val(resp.filePath);
numberedStepper.next();
}
}
});
}
$("#btnSelectJob").on("click", function(){
if($("#selectJob").val() == ""){
alert("처리 업무를 선택하세요.");
return;
}
numberedStepper.next();
});
$("#btnComplete").on("click", function(){
var data = {
filePath : $("#filePath").val(),
job : $("#selectJob").val(),
};
var param = "{ " + "'tmplatId'" + " : " + $("#tmplatId").val() + " }";
data.param = param;
ajax.post({
url : wctx.url("/link/fileProcess.do"),
data : data,
success : (resp) => {
alert("완료되었습니다.");
//window.close();
//if(resp.saved){
//}
}
});
});
wctx.csrf = window.opener.wctx.csrf;
</script>
</body>
</html>
Loading…
Cancel
Save