package kr.co.kihyun.beans.totsys.totper; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.URLDecoder; import java.net.URLEncoder; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; import javax.jdo.PersistenceManager; import javax.jdo.Transaction; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import kr.co.kihyun.beans.entity.MDept; import kr.co.kihyun.beans.entity.TotDoc; import kr.co.kihyun.beans.entity.TotReport; import kr.co.kihyun.beans.entity.TotReportProcess; import kr.co.kihyun.beans.entity.util.*; import kr.co.kihyun.beans.user.HttpSSOLogin; import kr.co.kihyun.db.CommonDBManager; import kr.co.kihyun.lang.MLong; import kr.co.kihyun.lang.MString; import kr.co.kihyun.moumi.MoumiConfig; import kr.co.kihyun.text.html.ServletUtil; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Servlet implementation class HttpFileDownLoad */ @WebServlet("/servlet/kr.co.kihyun.beans.totsys.totper.HttpFileDownLoad") public class HttpFileDownLoad extends HttpServlet { private static final long serialVersionUID = 1L; private static final Logger LOG = LoggerFactory.getLogger(HttpFileDownLoad.class); private static final int BUFFER = 4096; @Override public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { doPost(req, res); } @Override public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { if (!HttpSSOLogin.isLogin(req)) { String connURL = "location='/index.html';"; res.getWriter().println(""); res.getWriter().println(ServletUtil.getJavaScript(connURL)); return; } Long docID = MLong.parseLong(req.getParameter("docID")); Long repDocID = 0L; //LJH String saveAs=req.getParameter("saveAs"); String[] reportIDArray = MString.checkNull(req.getParameter("reportIDs")).split(","); //LOG.debug("[파라미터로 넘어온 reportIDArray 다음과 같다]["+reportIDArray+"]"); boolean setUserName = Boolean.parseBoolean(req.getParameter("setUserName")); res.setContentType("application/zip;charset=UTF-8"); //LJH String fname=URLEncoder.encode(saveAs, "UTF-8").replaceAll(":","_").replace("+", " ") +";"; String fnameE=URLEncoder.encode(saveAs, "UTF-8").replaceAll(":","_").replace("+", " ") +";"; String fnameD=URLDecoder.decode(saveAs, "UTF-8").replaceAll(":","_").replace("+", " ") +";"; //3.디렉토리 경로 조작(getParameter)_CWE-22/23/36 : Add by KWON,HAN fname = fnameD; if(fname.contains("..") || fname. contains("/")) { // 특수문자열 검증 return; } fname = fnameE; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ res.setHeader("Content-Disposition", "attachment; filename="+fname); byte data[] = new byte[BUFFER]; ZipArchiveOutputStream out = new ZipArchiveOutputStream(new BufferedOutputStream(res.getOutputStream())); out.setEncoding("UTF-8"); PersistenceManager pm = new MPersistenceManager(PMF.get().getPersistenceManager()); Transaction tx = pm.currentTransaction(); CommonDBManager acdbm=new CommonDBManager(); ResultSet rs= null; try { tx.begin(); TotDoc totDoc = pm.getObjectById(TotDoc.class, docID); //1. DB에 저장된 첨부파일의 총 크기를 가져 온다. by wonseok Lee 20170908 int file_check_cnt = 0; int report_cnt = 0; String speChar = "[^\uAC00-\uD7A3xfe0-9a-zA-Z\\s]"; //특수문자를 '_'로 변환하기 위한 변수 StringBuilder sql = new StringBuilder(250); File[] attachFileList = null; String qryString = ""; //LOG.debug("[선택한 reportIDArray 다음과 같다]["+reportIDArray.length+"]"); //체크박스 선택한 reportID 축출을 위한 쿼리문 추가함 by wonseok Lee 20170915 if (!(reportIDArray.length == 1 && reportIDArray[0].length() == 0)) { for(int i = 0; i < reportIDArray.length; i++){ if(i==0) { if(reportIDArray.length == 1 ){ qryString += " AND R.ID IN("+reportIDArray[i]+")"; continue; }else{ qryString += " AND R.ID IN("+reportIDArray[i]+","; } }else if(i == (reportIDArray.length-1)) { qryString += reportIDArray[i]+" )"; }else { qryString += " "+reportIDArray[i]+","; } } } LOG.debug("[선택한 reportID는 다음과 같다]["+qryString+"]"); sql.append(" SELECT COUNT(R.ID) AS REPORT_CNT, SUM(DECODE(FILE_CHECK,'Y',1,0)) AS FILE_CHECK_CNT"); sql.append(" FROM MOUMI_TOT_REPORT R"); sql.append(" WHERE 1=1"); sql.append(qryString); sql.append(" AND (R.DOC_ID =? OR R.REP_DOC_ID=?)"); sql.append(" AND R.DEL_TYPE='N'"); sql.append(" AND (R.PRSS='6' OR R.PRSS='14') "); LOG.debug("sql ===== " + sql); rs= acdbm.execQuery(sql,docID,docID); if(rs.next()){ report_cnt = rs.getInt(1); file_check_cnt = rs.getInt(2); } if(null != rs)rs.close(); acdbm.pstmt.close(); LOG.debug("report_cnt["+report_cnt+"] file_check_cnt["+file_check_cnt+"]"); long[] reportIDs = new long[report_cnt]; //제출ID String[] deptIDs = new String[report_cnt]; //부서ID String[] deptNames = new String[report_cnt]; //부서명ID String[] upperIDs = new String[report_cnt]; //상위부서ID String[] upperNames = new String[report_cnt]; //상위부서명ID String[] organIDs = new String[report_cnt]; //organID String[] organNames = new String[report_cnt]; //organ명 long[] repDocIDs = new long[report_cnt]; //docid String[] attacheFilePath = new String[report_cnt]; //2. reportID를 가져온다 sql.delete(0, sql.length()); sql.append(" SELECT R.ID,"); sql.append(" R.DEPT_ID,"); sql.append(" D.NAME,"); sql.append(" D.UPPER_DEPT,"); sql.append(" (SELECT NAME FROM MOUMI_DEPT WHERE ID=D.UPPER_DEPT) AS UPPER_DEPT_NAME,"); sql.append(" D.ORGAN, "); sql.append(" (SELECT NAME FROM MOUMI_DEPT WHERE ID=D.ORGAN) AS ORGAN_NAME,"); sql.append(" R.DOC_ID, "); sql.append(" D.SEL_TYPE"); sql.append(" FROM MOUMI_TOT_REPORT R,"); sql.append(" MOUMI_DEPT D"); sql.append(" WHERE 1=1 "); sql.append(qryString); sql.append(" AND (R.DOC_ID =? OR R.REP_DOC_ID=?) "); sql.append(" AND R.DEL_TYPE='N' "); sql.append(" AND (R.PRSS='6' OR R.PRSS='14')"); sql.append(" AND R.DEPT_ID=D.ID ") ; sql.append(" ORDER BY D.ORGAN , D.UPPER_DEPT, D.GRADE, D.FOUNDATION, D.NAME") ; LOG.debug("sql >>>>>>>>>>>>>>>>>>> ["+sql+"]"); rs= acdbm.execQuery(sql,docID,docID); for (int i = 0; rs.next(); i++) { reportIDs[i] = rs.getInt(1); deptIDs[i] = rs.getString(2); deptNames[i] = rs.getString(3); upperIDs[i] = rs.getString(4); upperNames[i] = rs.getString(5); organIDs[i] = rs.getString(6); organNames[i] = rs.getString(7); repDocIDs[i] = rs.getLong(8); } if(null != rs) rs.close(); acdbm.pstmt.close(); List totReports = new ArrayList(); List totReportsComp = new ArrayList(); List esbTotReportsComp = new ArrayList(); List totReportsNote = new ArrayList(); if (reportIDArray.length == 1 && reportIDArray[0].length() == 0) { totReportsComp = totDoc.getPrssReports(pm, TotReportProcess.COMP, "", null,null); //6:제출완료 esbTotReportsComp = totDoc.getRecursivePrssReports(pm, totReportsComp, null); //연계자료 조회 totReportsNote = totDoc.getPrssReports(pm, TotReportProcess.NOTE, "", null,null); //14:회수요청 for (TotReport report : esbTotReportsComp) { totReports.add(report); } for (TotReport report : totReportsNote) { totReports.add(report); } } else { LOG.debug("reportIDArray.length == 1 && reportIDArray[0].length()["+reportIDArray.length+"] ["+ reportIDArray[0].length() +"]" ); for (String reportIDStr : reportIDArray) { Long reportID = MLong.parseLong(reportIDStr); totReports.add(pm.getObjectById(TotReport.class, reportID)); } } for (TotReport report : totReports) { if(null == report.getAttachmentsPath() || "".equals(report.getAttachmentsPath())){ //파일패스가 없으면 디비에서 찾아라 for (Entry> entry : report.getAttachments().entrySet()) { MDept mDept = report.getDept(pm); MDept mDeptOrgan = mDept.getOrgan(pm); while (mDept != null && !mDept.isDocUnit()) mDept = mDept.getUpperDept(pm); StringBuilder entryGrName = new StringBuilder(mDeptOrgan.getName().replaceAll(speChar, "_")); StringBuilder entryName = new StringBuilder(mDept.getName().replaceAll(speChar, "_")); Byte[] content = entry.getValue().toArray(new Byte[]{}); byte[] contentPri = new byte[content.length]; for (int i = 0; i < content.length; i++) contentPri[i] = content[i]; BufferedInputStream origin = new BufferedInputStream(new ByteArrayInputStream(contentPri), BUFFER); try { if (setUserName) { entryName.append("_").append(report.getOwnerName(pm)); } entryGrName.append("_").append(entryName.append("_").append(entry.getKey())); ZipArchiveEntry zipEntry = new ZipArchiveEntry(entryGrName.toString()); out.putArchiveEntry(zipEntry); int count = 0; while ((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); } } catch (IOException e) { e.printStackTrace(); } finally { origin.close(); } } }else{ //파일패스가 있으면...서버에서 찾아라. long report_id = report.getId(); int jj = 0; for(int i=0; i < reportIDs.length; i++){ if(reportIDs[i] == report_id){ jj = i; break; } } attacheFilePath[jj] = MoumiConfig.getFileDirectory()+"/"+repDocIDs[jj]+"/"+reportIDs[jj]+"/"+deptIDs[jj]; LOG.debug("attacheFilePath[i] .["+attacheFilePath[jj]+"]"); File attachePath = new File(attacheFilePath[jj]); //디렉토리가 있고 if(attachePath.exists()){ attachFileList = attachePath.listFiles(); //파일이 있으면 if(attachFileList!=null) { for(int ii=0; ii< attachFileList.length; ii++) { StringBuilder entryGrName = new StringBuilder(organNames[jj].replaceAll(speChar, "_")); StringBuilder entryName = new StringBuilder(deptNames[jj].replaceAll(speChar, "_")); if (setUserName){ //entryName.append("_").append(report.(pm)); } entryGrName.append("_").append(entryName); ZipArchiveEntry zipEntry = new ZipArchiveEntry(entryGrName.toString()+"_"+attachFileList[ii].getName()); out.putArchiveEntry(zipEntry); if(attachFileList[ii].exists()){ FileInputStream fis = null; try { fis = new FileInputStream(attachFileList[ii]); byte[] content = new byte[(int) attachFileList[ii].length()]; fis.read(content); //파일의 내용을 읽는다. out.write(content); //읽은 파일내용을 압축파일에 쓴다. fis.close(); } catch (IOException e) { e.printStackTrace(); out.flush(); out.close(); } finally { fis.close(); //파일실행을 끊어줌.// 예외 발생 여부와 상관없이 자원 해제 } } } } } } } tx.rollback(); if (out.getCount() > 0) out.closeArchiveEntry(); out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); } finally { try{ if(null != rs) rs.close(); }catch(Exception e1){ e1.printStackTrace(); } acdbm.execClose(); if (tx.isActive()) tx.rollback(); pm.close(); } } }