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();
}
}
}