견문 첨부파일 일괄 다운로드 작업중.

master
강석 최 2023-01-20 16:53:36 +09:00
parent eaaafa71c5
commit 3b0e65702a
9 changed files with 265 additions and 132 deletions

View File

@ -54,6 +54,8 @@ public class BaseService {
protected String monitoringPath; protected String monitoringPath;
@Value("${file.dir.intelligenceNetwork}") @Value("${file.dir.intelligenceNetwork}")
protected String intelligenceNetworkPath; protected String intelligenceNetworkPath;
@Value("${file.dir.affairTemp}")
protected String affairTempPath;
protected String calculationSize(double fileSize){ protected String calculationSize(double fileSize){
String[] units = {"bytes", "KB", "MB", "GB", "TB", "PB"}; String[] units = {"bytes", "KB", "MB", "GB", "TB", "PB"};

View File

@ -20,10 +20,9 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.*; import java.io.*;
@ -31,6 +30,14 @@ import java.net.URLEncoder;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
@ -118,6 +125,78 @@ public class FileController extends BaseService{
e.printStackTrace(); e.printStackTrace();
} }
} }
@PostMapping("/downloadAffairFiles")
public void downloadAffairFiles(HttpServletRequest request,
HttpServletResponse response,
@RequestParam(value="affairKeyList") List<Integer> affairKeyList){
List<FileInfo> fileList = affairService.selectAffairFileList(affairKeyList);
List<Map<String, String>> fileInfoList = new ArrayList<>();
for(FileInfo file: fileList){
Map<String, String> fileInfoMap = new HashMap<>();
fileInfoMap.put("filePath", file.getSavePath()+File.separator+file.getConvNm());
fileInfoMap.put("originalName", file.getOrigNm()+"."+file.getFileExtn());
fileInfoList.add(fileInfoMap);
}
BufferedInputStream in = null;
BufferedOutputStream out = null;
String zipFile = locationPath+affairTempPath;
File saveFolder = new File(zipFile);
if (!saveFolder.exists() || saveFolder.isFile()) {
saveFolder.mkdirs();
}
String downloadFileName = "견문보고서 첨부파일_"+ LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))+".zip";
zipFile += File.separator+downloadFileName;
try{
setDisposition(zipFile, request, response);
// ZipOutputStream을 FileOutputStream 으로 감쌈
FileOutputStream fout = new FileOutputStream(zipFile);
ZipOutputStream zout = new ZipOutputStream(fout);
for(Map<String, String> fileMap: fileInfoList){
//본래 파일명 유지, 경로제외 파일압축을 위해 new File로
ZipEntry zipEntry = new ZipEntry(fileMap.get("originalName"));
zout.putNextEntry(zipEntry);
//경로포함 압축
//zout.putNextEntry(new ZipEntry(sourceFiles.get(i)));
FileInputStream fin = new FileInputStream(fileMap.get("filePath"));
byte[] buffer = new byte[1024];
int length;
// input file을 1024바이트로 읽음, zip stream에 읽은 바이트를 씀
while((length = fin.read(buffer)) > 0){
zout.write(buffer, 0, length);
}
zout.closeEntry();
fin.close();
}
zout.close();
response.setContentType("application/zip");
response.addHeader("Content-Disposition", "attachment; filename=" + downloadFileName);
in=new BufferedInputStream(new FileInputStream(zipFile));
out=new BufferedOutputStream(response.getOutputStream());
FileCopyUtils.copy(in, out);
out.flush();
/*byte[] data=new byte[2048];
int input=0;
while((input=in.read(data))!=-1){
out.write(data,0,input);
out.flush();
}*/
if(out!=null) out.close();
if(in!=null) in.close();
} catch(IOException e){
e.printStackTrace();
}
}
private FileInfo getFileInfo(String board, Integer parentKey, Integer fileSeq){ private FileInfo getFileInfo(String board, Integer parentKey, Integer fileSeq){
FileInfo downloadFile = null; FileInfo downloadFile = null;
switch (board){ switch (board){

View File

@ -110,7 +110,7 @@ public class CounterIntelligenceController {
if(ciWorkStatistics.getYear()==null){ if(ciWorkStatistics.getYear()==null){
ciWorkStatistics.setYear(LocalDateTime.now().getYear()); ciWorkStatistics.setYear(LocalDateTime.now().getYear());
} }
ModelAndView mav = new ModelAndView("/counterIntelligence/ciWork/ciWorkStatistics"); ModelAndView mav = new ModelAndView("counterIntelligence/ciWork/ciWorkStatistics");
mav.addObject("yearList", ciService.selectCiWorkYearList()); mav.addObject("yearList", ciService.selectCiWorkYearList());
mav.addObject("ciWorkStatisticsList", ciService.selectCiWorkStatisticsList(ciWorkStatistics)); mav.addObject("ciWorkStatisticsList", ciService.selectCiWorkStatisticsList(ciWorkStatistics));
mav.addObject("searchParams", ciWorkStatistics); mav.addObject("searchParams", ciWorkStatistics);

View File

@ -1,5 +1,6 @@
package com.dbnt.faisp.main.fpiMgt.affair; package com.dbnt.faisp.main.fpiMgt.affair;
import com.dbnt.faisp.config.FileInfo;
import com.dbnt.faisp.main.authMgt.service.AuthMgtService; import com.dbnt.faisp.main.authMgt.service.AuthMgtService;
import com.dbnt.faisp.main.codeMgt.service.CodeMgtService; import com.dbnt.faisp.main.codeMgt.service.CodeMgtService;
import com.dbnt.faisp.main.fpiMgt.affair.model.AffairBoard; import com.dbnt.faisp.main.fpiMgt.affair.model.AffairBoard;
@ -13,12 +14,15 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.HashMap; import java.time.format.DateTimeFormatter;
import java.util.Iterator; import java.util.*;
import java.util.List; import java.util.zip.ZipEntry;
import java.util.Map; import java.util.zip.ZipOutputStream;
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor

View File

@ -16,6 +16,7 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.File; import java.io.File;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ -180,6 +181,15 @@ public class AffairService extends BaseService { // 견문보고
return affairFileRepository.findById(new AffairFile.AffairFileId(parentKey, fileSeq)).orElse(null); return affairFileRepository.findById(new AffairFile.AffairFileId(parentKey, fileSeq)).orElse(null);
} }
public List<FileInfo> selectAffairFileList(List<Integer> affairKeyList) {
List<FileInfo> fileList = new ArrayList<>();
for(Integer affairKey: affairKeyList){
List<AffairFile> affairFileList = affairFileRepository.findByAffairKey(affairKey);
fileList.addAll(affairFileList);
}
return fileList;
}
public List<TypeStatistics> selectStatusTotal(TypeStatistics typeStatistics) { public List<TypeStatistics> selectStatusTotal(TypeStatistics typeStatistics) {
return affairMapper.selectStatusTotal(typeStatistics); return affairMapper.selectStatusTotal(typeStatistics);
} }

View File

@ -30,6 +30,8 @@ file.dir.majorStatus=/majorStatus
file.dir.monitoring=/monitoring file.dir.monitoring=/monitoring
file.dir.intelligenceNetwork=/intelligenceNetwork file.dir.intelligenceNetwork=/intelligenceNetwork
file.dir.affairTemp=/affairTemp
editor.img.view=/file/editorFileDisplay?fileNm= editor.img.view=/file/editorFileDisplay?fileNm=

View File

@ -27,10 +27,10 @@ $(document).on('click', '#commitTab', function (){
$(document).on('click', '.affairTr', function (event){ $(document).on('click', '.affairTr', function (event){
const target = event.target; const target = event.target;
if(!(target.className === "apprvTd" || $(target).parents(".apprvTd").length>0)){ if(!(target.className === "apprvTd" || $(target).parents(".apprvTd").length>0)){
const chkBox = $(this).find(".rowChkBox"); const chkBox = $(this).find(".trChkBox");
if(chkBox.length>0){ if(chkBox.length>0){
$(".trChkBox").prop("checked", false); $(".trChkBox").prop("checked", false);
chkBox[0].checked = !chkBox[0].checked; chkBox[0].checked = true;
} }
getAffairViewModal(Number($(this).find(".affairKey").val())); getAffairViewModal(Number($(this).find(".affairKey").val()));
} }
@ -147,6 +147,37 @@ $(document).on('change', '.apprvChkbox', function (){
} }
}) })
$(document).on('click', '#fileDownBtn', function (){
const selectedList = $(".trChkBox:checked")
if(selectedList.length<1){
alert("대상이 없습니다.");
return false;
}
if(confirm("선택된 견문의 파일을 다운로드 하시겠습니까?")){
const formData = new FormData();
$.each(selectedList, function(idx, chkBox){
formData.append("affairKeyList", $(chkBox).parents("tr").find(".affairKey").val());
})
contentFade("in");
$.ajax({
type : 'POST',
data : formData,
url : "/file/downloadAffairFiles",
processData: false,
contentType: false,
beforeSend: function (xhr){
xhr.setRequestHeader($("[name='_csrf_header']").val(), $("[name='_csrf']").val());
},
success : function(result) {
contentFade("out");
},
error : function(xhr, status) {
contentFade("out");
}
})
}
})
function getAffairViewModal(affairKey){ function getAffairViewModal(affairKey){
$.ajax({ $.ajax({
url: '/affair/affairViewModal', url: '/affair/affairViewModal',

View File

@ -129,7 +129,7 @@
<table class="table table-sm table-bordered table-hover mb-2"> <table class="table table-sm table-bordered table-hover mb-2">
<thead> <thead>
<tr class="table-secondary"> <tr class="table-secondary">
<th></th> <th><input type="checkbox" class="allChk"></th>
<th>문서번호</th> <th>문서번호</th>
<th>분야1</th> <th>분야1</th>
<th>분야2</th> <th>분야2</th>
@ -254,6 +254,7 @@
</div> </div>
<div class="row justify-content-between"> <div class="row justify-content-between">
<div class="col-auto"> <div class="col-auto">
<button type="button" class="btn btn-sm btn-info" id="fileDownBtn">첨부파일 다운로드</button>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<nav aria-label="Page navigation"> <nav aria-label="Page navigation">

View File

@ -31,11 +31,11 @@
<label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">보고일자</label> <label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">보고일자</label>
<label class="col-sm-2 border-end border-secondary col-form-label col-form-label-sm text-start" th:text="${#temporals.format(affair.reportDt, 'yyyy-MM-dd')}"></label> <label class="col-sm-2 border-end border-secondary col-form-label col-form-label-sm text-start" th:text="${#temporals.format(affair.reportDt, 'yyyy-MM-dd')}"></label>
<label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">공개여부</label> <label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">공개여부</label>
<label class="col-sm-2 border-end border-secondary col-form-label col-form-label-sm text-start">
<th:block th:each="code:${session.commonCode.get('AVS')}"> <th:block th:each="code:${session.commonCode.get('AVS')}">
<th:block th:if="${code.itemCd eq affair.viewStatus}"> <th:block th:if="${code.itemCd eq affair.viewStatus}" th:text="${code.itemValue}"></th:block>
<label class="col-sm-2 border-end border-secondary col-form-label col-form-label-sm text-start" th:text="${code.itemValue}"></label>
</th:block>
</th:block> </th:block>
</label>
<label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">상태</label> <label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">상태</label>
<th:block th:each="code:${session.commonCode.get('DST')}"> <th:block th:each="code:${session.commonCode.get('DST')}">
<th:block th:if="${code.itemCd eq affair.affairStatus}"> <th:block th:if="${code.itemCd eq affair.affairStatus}">
@ -46,49 +46,49 @@
<hr> <hr>
<div class="row border border-secondary"> <div class="row border border-secondary">
<label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">제목</label> <label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">제목</label>
<label class="col-sm-11 border-end border-secondary col-form-label col-form-label-sm text-start" th:text="${affair.title}"></label> <label class="col-sm-11 col-form-label col-form-label-sm text-start" th:text="${affair.title}"></label>
</div> </div>
<div class="row border border-top-0 border-secondary"> <div class="row border border-top-0 border-secondary">
<label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">분야1</label> <label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">분야1</label>
<label class="col-sm-2 border-end border-secondary col-form-label col-form-label-sm text-start">
<th:block th:each="code:${session.commonCode.get('DC01')}"> <th:block th:each="code:${session.commonCode.get('DC01')}">
<th:block th:if="${code.itemCd eq affair.affairType1}"> <th:block th:if="${code.itemCd eq affair.affairType1}" th:text="${code.itemValue}"></th:block>
<label class="col-sm-2 border-end border-secondary col-form-label col-form-label-sm text-start" th:text="${code.itemValue}"></label>
</th:block>
</th:block> </th:block>
</label>
<label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">분야2</label> <label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">분야2</label>
<label class="col-sm-2 border-end border-secondary col-form-label col-form-label-sm text-start">
<th:block th:each="code:${session.commonCode.get('DC02')}"> <th:block th:each="code:${session.commonCode.get('DC02')}">
<th:block th:if="${code.itemCd eq affair.affairType2}"> <th:block th:if="${code.itemCd eq affair.affairType2}" th:text="${code.itemValue}"></th:block>
<label class="col-sm-2 border-end border-secondary col-form-label col-form-label-sm text-start" th:text="${code.itemValue}"></label>
</th:block>
</th:block> </th:block>
</label>
<label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">분야3</label> <label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">분야3</label>
<label class="col-sm-2 border-end border-secondary col-form-label col-form-label-sm text-start">
<th:block th:each="code:${session.commonCode.get('DC03')}"> <th:block th:each="code:${session.commonCode.get('DC03')}">
<th:block th:if="${code.itemCd eq affair.affairType3}"> <th:block th:if="${code.itemCd eq affair.affairType3}" th:text="${code.itemValue}"></th:block>
<label class="col-sm-2 border-end border-secondary col-form-label col-form-label-sm text-start" th:text="${code.itemValue}"></label>
</th:block>
</th:block> </th:block>
</label>
<label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">분야4</label> <label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">분야4</label>
<label class="col-sm-2 col-form-label col-form-label-sm text-start">
<th:block th:each="code:${session.commonCode.get('DC04')}"> <th:block th:each="code:${session.commonCode.get('DC04')}">
<th:block th:if="${code.itemCd eq affair.affairType4}"> <th:block th:if="${code.itemCd eq affair.affairType4}" th:text="${code.itemValue}"></th:block>
<label class="col-sm-2 border-end border-secondary col-form-label col-form-label-sm text-start" th:text="${code.itemValue}"></label>
</th:block>
</th:block> </th:block>
</label>
</div> </div>
<hr> <hr>
<div class="row border border-top-0 border-secondary"> <div class="row border border-secondary">
<label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">내용</label> <label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">내용</label>
<div class="col-sm-11 form-control-sm" id="contentDiv"> <div class="col-sm-11 form-control-sm" id="contentDiv">
<div th:utext="${affair.content}"></div> <div th:utext="${affair.content}"></div>
</div> </div>
</div> </div>
<hr> <hr>
<div class="row border border-top-0 border-secondary"> <div class="row border border-secondary">
<label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">해시태그</label> <label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">해시태그</label>
<label class="col-sm-11 border-end border-secondary col-form-label col-form-label-sm text-start" th:text="${affair.hashTags}"></label> <label class="col-sm-11 col-form-label col-form-label-sm text-start" th:text="${affair.hashTags}"></label>
</div> </div>
<div class="row border border-top-0 border-secondary"> <div class="row border border-top-0 border-secondary">
<label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">비고</label> <label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">비고</label>
<label class="col-sm-11 border-end border-secondary col-form-label col-form-label-sm text-start" th:text="${affair.etc}"></label> <label class="col-sm-11 col-form-label col-form-label-sm text-start" th:text="${affair.etc}"></label>
</div> </div>
</div> </div>
<div class="tab-pane fade p-2" id="fileTabPanel" role="tabpanel" tabindex="0"> <div class="tab-pane fade p-2" id="fileTabPanel" role="tabpanel" tabindex="0">
@ -117,21 +117,22 @@
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="row border border-top-0 border-secondary"> <div class="row">
<div class="col-12" th:unless="${#lists.isEmpty(affair.rateList)}"> <div class="col-12" th:unless="${#lists.isEmpty(affair.rateList)}">
<div class="px-2">
<hr> <hr>
<th:block th:each="rate:${affair.rateList}"> <th:block th:each="rate:${affair.rateList}">
<div class="row border border-top-0 border-secondary py-1"> <div class="row border border-secondary">
<label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold"> <label class="col-sm-1 border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">
<th:block th:each="code:${session.commonCode.get('OG')}"> <th:block th:each="code:${session.commonCode.get('OG')}">
<th:block th:if="${code.itemCd eq rate.ratingOrgan}" th:text="${code.itemValue}"></th:block> <th:block th:if="${code.itemCd eq rate.ratingOrgan}" th:text="${code.itemValue}"></th:block>
</th:block> </th:block>
</label> </label>
<div class="col-auto"> <div class="col-auto">
<div class="row border border-top-0 border-secondary" th:if="${rate.sectionApprv eq null}"> <div class="row" th:if="${rate.sectionApprv eq null}">
<label class="col-sm-auto border-end border-secondary col-form-label col-form-label-sm text-center">결재정보가 없습니다.</label> <label class="col-sm-auto border-end border-secondary col-form-label col-form-label-sm text-center">결재정보가 없습니다.</label>
</div> </div>
<div class="row border border-top-0 border-secondary" th:if="${rate.sectionApprv ne null}"> <div class="row" th:if="${rate.sectionApprv ne null}">
<label class="col-sm-auto border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">결재결과: </label> <label class="col-sm-auto border-end border-secondary col-form-label col-form-label-sm text-center fw-bold">결재결과: </label>
<label class="col-sm-auto border-end border-secondary col-form-label col-form-label-sm text-start"> <label class="col-sm-auto border-end border-secondary col-form-label col-form-label-sm text-start">
<th:block th:each="code:${session.commonCode.get('DST')}"> <th:block th:each="code:${session.commonCode.get('DST')}">
@ -177,7 +178,9 @@
</div> </div>
</th:block> </th:block>
</div> </div>
</div>
<div class="col-12" th:if="${apprvAuth ne null}"> <div class="col-12" th:if="${apprvAuth ne null}">
<div class="px-2">
<form action="#" method="post" id="apprvForm"> <form action="#" method="post" id="apprvForm">
<input type="hidden" name="affairKey" th:value="${affair.affairKey}"> <input type="hidden" name="affairKey" th:value="${affair.affairKey}">
<th:block th:if="${(apprvAuth eq 'APC003' or apprvAuth eq 'APC004') and affair.affairStatus eq 'DST002' and affair.rateList.get(0).ratingOrgan eq userOrgan}"> <th:block th:if="${(apprvAuth eq 'APC003' or apprvAuth eq 'APC004') and affair.affairStatus eq 'DST002' and affair.rateList.get(0).ratingOrgan eq userOrgan}">
@ -227,6 +230,7 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="modal-footer bg-light"> <div class="modal-footer bg-light">
<th:block th:unless="${affair.affairStatus eq 'DST004' or affair.affairStatus eq 'DST006'}"> <th:block th:unless="${affair.affairStatus eq 'DST004' or affair.affairStatus eq 'DST006'}">
<!--승인 상태일때는 수정 불가--> <!--승인 상태일때는 수정 불가-->