diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/faq/controller/CnsFaqController.java b/pav-server/src/main/java/com/palnet/biz/api/cns/faq/controller/CnsFaqController.java new file mode 100644 index 00000000..a3cfbfdf --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/faq/controller/CnsFaqController.java @@ -0,0 +1,74 @@ +package com.palnet.biz.api.cns.faq.controller; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.cns.faq.model.FaqListRQModel; +import com.palnet.biz.api.cns.faq.model.FaqListModel; +import com.palnet.biz.api.cns.faq.service.CnsFaqService; +import com.palnet.biz.api.comn.response.BasicResponse; +import com.palnet.biz.api.comn.response.SuccessResponse; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RestController +@Slf4j +@RequiredArgsConstructor +@RequestMapping(value = "/api/bas/cns/faq") +public class CnsFaqController { + + private final CnsFaqService service; + + /*FAQ 목록 조회*/ + @PostMapping("/list") + public ResponseEntity getFaqList(@RequestBody FaqListRQModel model) { + + List result = null; + + result = service.getFaqList(model); + + return ResponseEntity.ok().body(new SuccessResponse<>(result)); + } + + /*FAQ 상세 조회*/ + @GetMapping("/detail") + public ResponseEntity getFaqDetail(int sno) { + + FaqListModel result = null; + + result = service.getFaqDetail(sno); + + return ResponseEntity.ok().body(result); + } + + /*FAQ 작성*/ + @PostMapping("/insert") + public void insertFaq(@RequestBody FaqListModel model) { + + service.insertFaq(model); + + } + + /*FAQ 업데이트*/ + @PostMapping("/update") + public void updateFaq(@RequestBody FaqListModel model) { + + service.updateFaq(model); + + } + + /*FAQ 논리 삭제*/ + @PostMapping("/delete") + public void deleteFaq(int sno) { + + service.deleteFaq(sno); + + } +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/faq/model/FaqListModel.java b/pav-server/src/main/java/com/palnet/biz/api/cns/faq/model/FaqListModel.java new file mode 100644 index 00000000..891a7a1c --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/faq/model/FaqListModel.java @@ -0,0 +1,32 @@ +package com.palnet.biz.api.cns.faq.model; + +import java.time.Instant; + +import lombok.Data; + +@Data +public class FaqListModel { + + private int faqSno; + + private String category; + + private String title; + + private String content; + + private int viewCnt; + + private String expsrYn; + + private String delYn; + + private String createUserId; + + private Instant createDt; + + private String updateUserId; + + private Instant updateDt; + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/faq/model/FaqListRQModel.java b/pav-server/src/main/java/com/palnet/biz/api/cns/faq/model/FaqListRQModel.java new file mode 100644 index 00000000..1be952de --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/faq/model/FaqListRQModel.java @@ -0,0 +1,12 @@ +package com.palnet.biz.api.cns.faq.model; + +import lombok.Data; + +@Data +public class FaqListRQModel { + + private String category; + + private String word; + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/faq/service/CnsFaqService.java b/pav-server/src/main/java/com/palnet/biz/api/cns/faq/service/CnsFaqService.java new file mode 100644 index 00000000..d6a105e2 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/faq/service/CnsFaqService.java @@ -0,0 +1,105 @@ +package com.palnet.biz.api.cns.faq.service; + +import java.time.Instant; +import java.util.List; + +import javax.transaction.Transactional; + +import org.springframework.stereotype.Service; + +import com.palnet.biz.api.cns.faq.model.FaqListModel; +import com.palnet.biz.api.cns.faq.model.FaqListRQModel; +import com.palnet.biz.jpa.entity.CnsFaqBas; +import com.palnet.biz.jpa.repository.cns.CnsFaqBasRepository; +import com.palnet.biz.jpa.repository.cns.CnsFaqQueryRepository; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@RequiredArgsConstructor +public class CnsFaqService { + + private final CnsFaqQueryRepository query; + + private final CnsFaqBasRepository cnsFaqBasRepository; + + public List getFaqList(FaqListRQModel model){ + + List result = query.getFaqList(model.getCategory(), model.getWord()); + + if(result == null || result.size() < 1) throw new CustomException(ErrorCode.DATA_NO); + + return result; + + } + + public FaqListModel getFaqDetail(int sno){ + + cnsFaqBasRepository.updateViewCnt(sno); + + FaqListModel result = query.getFaqDetail(sno); + + if(result == null) throw new CustomException(ErrorCode.DATA_NO); + + return result; + + } + + @Transactional + public void insertFaq(FaqListModel model){ + + CnsFaqBas bas = new CnsFaqBas(); + + bas.setCreateDt(Instant.now()); + bas.setUpdateDt(Instant.now()); + + bas.setCategory(model.getCategory()); + bas.setContent(model.getContent()); + bas.setCreateUserId(model.getCreateUserId()); + bas.setDelYn(model.getDelYn()); + bas.setExpsrYn(model.getExpsrYn()); + bas.setTitle(model.getTitle()); + bas.setUpdateUserId(model.getUpdateUserId()); + bas.setViewCnt(0); + + try { + cnsFaqBasRepository.save(bas); + } catch(Exception e) { + throw new CustomException(ErrorCode.NON_VALID_PARAMETER); + } + } + + @Transactional + public void updateFaq(FaqListModel model) { + + FaqListModel prevData = query.getFaqDetail(model.getFaqSno()); + + if(prevData == null) throw new CustomException(ErrorCode.DATA_NO); + + if(model.getCategory() != null) prevData.setCategory(model.getCategory()); + if(model.getTitle() != null) prevData.setTitle(model.getTitle()); + if(model.getContent() != null) prevData.setContent(model.getContent()); + if(model.getExpsrYn() != null) prevData.setExpsrYn(model.getExpsrYn()); + if(model.getUpdateUserId() != null) prevData.setUpdateUserId(model.getUpdateUserId()); + + prevData.setUpdateDt(Instant.now()); + + try { + query.updateFaq(prevData); + } catch(Exception e) { + throw new CustomException(ErrorCode.NON_VALID_PARAMETER); + } + } + + public void deleteFaq(int sno) { + + int delCnt = cnsFaqBasRepository.deleteFaq(sno); + + if(delCnt == 0) throw new CustomException(ErrorCode.DATA_NO); + + } +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/controller/CnsQnaController.java b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/controller/CnsQnaController.java new file mode 100644 index 00000000..5716f7a9 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/controller/CnsQnaController.java @@ -0,0 +1,102 @@ +package com.palnet.biz.api.cns.qna.controller; + +import java.util.List; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.palnet.biz.api.cns.qna.model.QnaBasModel; +import com.palnet.biz.api.cns.qna.model.QnaDetailRSModel; +import com.palnet.biz.api.cns.qna.model.QnaInsertRQModel; +import com.palnet.biz.api.cns.qna.model.QnaRSModel; +import com.palnet.biz.api.cns.qna.model.QnaSelectListRQ; +import com.palnet.biz.api.cns.qna.service.CnsQnaService; + +import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@RestController +@Slf4j +@RequiredArgsConstructor +@RequestMapping("/api/cns/qna") +public class CnsQnaController { + + private final CnsQnaService cnsQnaService; + + + @PostMapping(value = "/insert", consumes = "multipart/form-data") + @Tag(name = "QNA", description = "QNA 관련 API") + @ApiOperation(value = "QnA 등록[답변추가]") + public ResponseEntity insertQna(QnaInsertRQModel rq){ + + boolean result = cnsQnaService.insertQna(rq); + + return ResponseEntity.ok().body(result); + } + + @GetMapping("/select") + @Tag(name = "QNA", description = "QNA 관련 API") + @ApiOperation(value = "QnA 리스트 조회") + public ResponseEntity> selectQna(QnaSelectListRQ rq){ + + List result = cnsQnaService.selectQnaList(rq); + + return ResponseEntity.ok().body(result); + } + + + @GetMapping("/{qnaSno}/detail") + @Tag(name = "QNA", description = "QNA 관련 API") + @ApiOperation(value = "QnA 상세보기") + public ResponseEntity> detailQna(@PathVariable int qnaSno){ + + List reulst = cnsQnaService.getQnaDetail(qnaSno); + + return ResponseEntity.ok().body(reulst); + } + + @PostMapping("/{qnaSno}/update") + @Tag(name = "QNA", description = "QNA 관련 API") + @ApiOperation(value = "QnA 업데이트") + public ResponseEntity updateQna(@PathVariable int qnaSno, QnaInsertRQModel rq){ + + boolean result = cnsQnaService.updateQna(qnaSno, rq); + + return ResponseEntity.ok().body(result); + } + + @GetMapping("/{qnaSno}/delete") + @Tag(name = "QNA", description = "QNA 관련 API") + @ApiOperation(value = "QnA 삭제하기") + public ResponseEntity deleteQna(@PathVariable int qnaSno){ + + boolean result = cnsQnaService.deleteQna(qnaSno); + + return ResponseEntity.ok().body(result); + } + + /** + * Qna Files 개별삭제 TODO:: 파일 업데이트의 기획이 어떻게 되는지 모름 + * @param qnaSno + * @param fileSno + * @return + */ + @GetMapping("/{qnaSno}/{fileSno}/delete") + @Tag(name = "QNA", description = "QNA 관련 API") + @ApiOperation(value = "QnA 파일 개별삭제") + public ResponseEntity deleteQnaFile(@PathVariable int qnaSno, @PathVariable int fileSno){ + log.warn("CnsQnaController - deleteQnaFile()"); + + boolean result = cnsQnaService.deleteQnaFile(fileSno); + + return ResponseEntity.ok().body(result); + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaBasModel.java b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaBasModel.java new file mode 100644 index 00000000..945df598 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaBasModel.java @@ -0,0 +1,36 @@ +package com.palnet.biz.api.cns.qna.model; + +import java.time.Instant; + +import lombok.Data; + +@Data +public class QnaBasModel { + + private int qnaSno; + + private int targetSno; + + private String category; + + private String title; + + private String content; + + private int fileGroupNo; + + private String expsrYn; + + private String delYn; + + private int viewCnt; + + private String createUserId; + + private Instant createDt; + + private String updateUserId; + + private Instant updateDt; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaDetailRSModel.java b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaDetailRSModel.java new file mode 100644 index 00000000..c86bf5c3 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaDetailRSModel.java @@ -0,0 +1,34 @@ +package com.palnet.biz.api.cns.qna.model; + +import java.time.Instant; +import java.util.List; + +import com.palnet.biz.jpa.entity.ComFileBas; + +import lombok.Data; + +@Data +public class QnaDetailRSModel { + + private int qnaSno; + + private int targetSno; + + private String category; + + private String title; + + private String content; + + private Integer viewCnt; + + private String createUserId; + + private Instant createDt; + + private String updateUserId; + + private Instant updateDt; + + private List files; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaInsertRQModel.java b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaInsertRQModel.java new file mode 100644 index 00000000..a07315d0 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaInsertRQModel.java @@ -0,0 +1,23 @@ +package com.palnet.biz.api.cns.qna.model; + +import java.util.List; + +import org.springframework.web.multipart.MultipartFile; + +import lombok.Data; + +@Data +public class QnaInsertRQModel { + + private Integer qnaSno; + + private Integer targetSno; // 상위 Qna 번호 + + private String category; + + private String title; + + private String content; + + private List files; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaRSModel.java b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaRSModel.java new file mode 100644 index 00000000..9295a360 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaRSModel.java @@ -0,0 +1,33 @@ +package com.palnet.biz.api.cns.qna.model; + +import lombok.Data; + +@Data +public class QnaRSModel{ + + private int code; + + private String desc; + + private Object body; + + public QnaRSModel() { + this.code = 200; + } + + public QnaRSModel(Object body){ + this.code = 200; + this.body = body; + } + + public QnaRSModel(int code, Object body){ + this.code = code; + this.body = body; + } + + public QnaRSModel(int code, String desc, Object body){ + this.code = code; + this.desc = desc; + this.body = body; + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaSelectListRQ.java b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaSelectListRQ.java new file mode 100644 index 00000000..ccd1b760 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/model/QnaSelectListRQ.java @@ -0,0 +1,11 @@ +package com.palnet.biz.api.cns.qna.model; + +import lombok.Data; + +@Data +public class QnaSelectListRQ { + + private String word; + + private String category; +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/cns/qna/service/CnsQnaService.java b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/service/CnsQnaService.java new file mode 100644 index 00000000..63d0b916 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/cns/qna/service/CnsQnaService.java @@ -0,0 +1,216 @@ +package com.palnet.biz.api.cns.qna.service; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +import javax.transaction.Transactional; + +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.api.cns.qna.model.QnaBasModel; +import com.palnet.biz.api.cns.qna.model.QnaDetailRSModel; +import com.palnet.biz.api.cns.qna.model.QnaInsertRQModel; +import com.palnet.biz.api.cns.qna.model.QnaSelectListRQ; +import com.palnet.biz.api.comn.file.service.ComnFileService; +import com.palnet.biz.jpa.entity.CnsQnaBas; +import com.palnet.biz.jpa.entity.ComFileBas; +import com.palnet.biz.jpa.repository.cns.CnsQnaBasRepository; +import com.palnet.biz.jpa.repository.cns.CnsQnaQueryRepository; +import com.palnet.biz.jpa.repository.com.ComFileBasRepository; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Service +@Slf4j +@RequiredArgsConstructor +public class CnsQnaService { + + private final CnsQnaBasRepository cnsQnaBasRepository; + + private final CnsQnaQueryRepository cnsQnaQueryRepository; + + private final ComFileBasRepository comFileBasRepository; + + private final ComnFileService comnFileService; + + private final JwtTokenUtil jwtTokenUtil; + + + public boolean deleteQnaFile(int fileSno){ + + comnFileService.deleteFile(fileSno); + + return true; + } + + /** + * Qna 삭제하기, file들도 모두 논리삭제함. + * @param qnaSno + * @return + */ + @Transactional + public boolean deleteQna(int qnaSno){ + + CnsQnaBas entity = cnsQnaBasRepository.findByQnaSnoAndDelYnAndExpsrYn(qnaSno, "N", "Y"); + if(entity == null) throw new CustomException(ErrorCode.DATA_NOTFIND); + + if(entity.getFileGroupNo() != null) comnFileService.deleteFiles(entity.getFileGroupNo()); + + entity.setDelYn("Y"); + + List deleteList = new ArrayList<>(); + deleteList.add(entity); + + int targetSno = qnaSno; + + // 대댓글 불러오기 + while(true){ + + CnsQnaBas cnsQnaBas = cnsQnaBasRepository.findFirstByTargetSnoAndDelYnAndExpsrYn(targetSno, "N", "Y"); + if(cnsQnaBas == null) break; + + cnsQnaBas.setDelYn("Y"); + + deleteList.add(cnsQnaBas); + + targetSno = cnsQnaBas.getQnaSno(); + } + + deleteList = cnsQnaBasRepository.saveAll(deleteList); + + return true; + } + + /** + * Qna 업데이트하기 TODO :: File 업데이트 기능 아직 구현안함 + * @param qnaSno + * @param rq + * @return + */ + @Transactional + public boolean updateQna(int qnaSno, QnaInsertRQModel rq){ + + CnsQnaBas entity = cnsQnaBasRepository.findFirstByQnaSnoAndTargetSnoAndDelYnAndExpsrYn(qnaSno, 0, "N", "Y"); + if(entity == null) throw new CustomException(ErrorCode.DATA_NOTFIND); + + List files = rq.getFiles(); + if(files != null && files.size() > 0) comnFileService.fileUpload(files, entity.getFileGroupNo()); // File 업로드 + + if(rq.getCategory() != null) entity.setCategory(rq.getCategory()); + if(rq.getContent() != null) entity.setContent(rq.getContent()); + if(rq.getTitle() != null) entity.setTitle(rq.getTitle()); + + cnsQnaBasRepository.save(entity); + + return true; + } + + /** + * Qna 상세불러오기 + * @param qnaSno + * @return + */ + @Transactional // 조회수 증가하기떄문 + public List getQnaDetail(int qnaSno){ + + cnsQnaBasRepository.pulsViewCount(qnaSno); + + CnsQnaBas qnaBasModel = cnsQnaBasRepository.findFirstByQnaSnoAndTargetSnoAndDelYnAndExpsrYn(qnaSno, 0, "N", "Y"); + List files = null; + if(qnaBasModel.getFileGroupNo() != 0) files = comFileBasRepository.findByFileGroupNoAndDelYn(qnaBasModel.getFileGroupNo(), "N"); + + QnaDetailRSModel node = new QnaDetailRSModel(); + node.setQnaSno(qnaSno); + node.setTargetSno(qnaBasModel.getTargetSno()); + node.setCategory(qnaBasModel.getCategory()); + node.setTitle(qnaBasModel.getTitle()); + node.setContent(qnaBasModel.getContent()); + node.setViewCnt(qnaBasModel.getViewCnt()); + node.setCreateUserId(qnaBasModel.getCreateUserId()); + node.setCreateDt(qnaBasModel.getCreateDt()); + node.setUpdateUserId(qnaBasModel.getUpdateUserId()); + node.setUpdateDt(qnaBasModel.getUpdateDt()); + node.setFiles(files); + + List result = new ArrayList<>(); + result.add(node); + + int targetSno = qnaSno; + + // 대댓글 불러오기 + while(true){ + + CnsQnaBas cnsQnaBas = cnsQnaBasRepository.findFirstByTargetSnoAndDelYnAndExpsrYn(targetSno, "N", "Y"); + if(cnsQnaBas == null) break; + + QnaDetailRSModel detailNode = new QnaDetailRSModel(); + detailNode.setQnaSno(cnsQnaBas.getQnaSno()); + detailNode.setTargetSno(cnsQnaBas.getTargetSno()); + detailNode.setCategory(cnsQnaBas.getCategory()); + detailNode.setTitle(cnsQnaBas.getTitle()); + detailNode.setContent(cnsQnaBas.getContent()); + detailNode.setCreateUserId(cnsQnaBas.getCreateUserId()); + detailNode.setCreateDt(cnsQnaBas.getCreateDt()); + detailNode.setUpdateUserId(cnsQnaBas.getUpdateUserId()); + detailNode.setUpdateDt(cnsQnaBas.getUpdateDt()); + + result.add(detailNode); + + targetSno = cnsQnaBas.getQnaSno(); + } + + return result; + } + + /** + * Qna리스트 조회 + * @param rq + * @return + */ + public List selectQnaList(QnaSelectListRQ rq){ + + return cnsQnaQueryRepository.getQnaList(rq.getCategory(), rq.getCategory()); + } + + /** + * QnaInsert + * @param rq + * @return + */ + @Transactional + public boolean insertQna(QnaInsertRQModel rq){ + + List files = rq.getFiles(); + Integer fileGroupNo = null; + if(files != null && files.size() > 0) fileGroupNo = comnFileService.fileUpload(files, null); // File 업로드 + + String userId = jwtTokenUtil.getUserIdByToken(); + + if (userId == null) userId = "NONE"; + + CnsQnaBas cnsQnaBas = new CnsQnaBas(); + cnsQnaBas.setCategory(rq.getCategory()); + cnsQnaBas.setTitle(rq.getTitle()); + cnsQnaBas.setContent(rq.getContent()); + cnsQnaBas.setCreateDt(Instant.now()); + cnsQnaBas.setCreateUserId(userId); + cnsQnaBas.setUpdateDt(Instant.now()); + cnsQnaBas.setUpdateUserId(userId); + cnsQnaBas.setExpsrYn("Y"); + + if(fileGroupNo != null) cnsQnaBas.setFileGroupNo(fileGroupNo); + if(rq.getTargetSno() != null) cnsQnaBas.setTargetSno(rq.getTargetSno()); + + cnsQnaBasRepository.save(cnsQnaBas); + + return true; + } + + +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/comn/file/constant/ExtensionConstant.java b/pav-server/src/main/java/com/palnet/biz/api/comn/file/constant/ExtensionConstant.java new file mode 100644 index 00000000..295a8099 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/api/comn/file/constant/ExtensionConstant.java @@ -0,0 +1,39 @@ +package com.palnet.biz.api.comn.file.constant; + +import java.util.HashSet; + +public enum ExtensionConstant { + JPG(".jpg"), + PNG(".png"), + JPEG(".jpeg"), + PDF(".pdf"), + XLSX(".xlsx"), + XLS(".xls"), + HWPX(".hwpx"), + HWP(".hwp"), + + ; + + public final String extension; + + public HashSet hashExtension; + + private ExtensionConstant(String extension) { + this.extension = extension; + } + + public static ExtensionConstant fromExtension(String extension) { + try { + for (ExtensionConstant constant : ExtensionConstant.values()) { + if (constant.extension.equals(extension)) { + + return constant; + } + } + } catch (Exception e) { + return null; + } + + return null; + } +} diff --git a/pav-server/src/main/java/com/palnet/biz/api/comn/file/service/ComnFileService.java b/pav-server/src/main/java/com/palnet/biz/api/comn/file/service/ComnFileService.java index 8c5a86af..ada9e1c9 100644 --- a/pav-server/src/main/java/com/palnet/biz/api/comn/file/service/ComnFileService.java +++ b/pav-server/src/main/java/com/palnet/biz/api/comn/file/service/ComnFileService.java @@ -1,6 +1,32 @@ package com.palnet.biz.api.comn.file.service; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import javax.servlet.http.HttpServletResponse; +import javax.transaction.Transactional; + +import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + import com.palnet.biz.api.acnt.jwt.utils.JwtTokenUtil; +import com.palnet.biz.api.comn.file.constant.ExtensionConstant; import com.palnet.biz.api.comn.file.model.LaancPdfModel; import com.palnet.biz.jpa.entity.ComFileBas; import com.palnet.biz.jpa.repository.com.ComFileBasRepository; @@ -8,20 +34,9 @@ import com.palnet.comn.code.ErrorCode; import com.palnet.comn.exception.CustomException; import com.palnet.comn.utils.InstantUtils; import com.palnet.comn.utils.PdfUtils; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.IOUtils; -import org.springframework.core.io.ClassPathResource; -import org.springframework.stereotype.Service; - -import javax.transaction.Transactional; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.time.Instant; -import java.util.Base64; @Slf4j @RequiredArgsConstructor @@ -30,9 +45,14 @@ public class ComnFileService { private final PdfUtils pdfUtils; private final JwtTokenUtil jwtTokenUtil; - private final ComFileBasRepository comFileBasRepository; + private final ComFileBasRepository comFileBasRepository; + private final HttpServletResponse response; - private final String FILE_EXTENSION = ".pdf"; + + @Value("${base-url}") + private String BASE_PATH; + + private final String NORMAL_FORDER_PATH = "normal/"; /** * 파일명 만들기, 앞에 기본으로 금일 날짜있음 @@ -41,7 +61,7 @@ public class ComnFileService { * @param etcName * @return */ - private String getLaancSaveName(String... etcName) { + private String getLaancSaveName(ExtensionConstant extension, String... etcName) { String date = InstantUtils.toDatetimeStringByFormat(Instant.now(), "yyyyMMddHHmmss"); @@ -53,7 +73,7 @@ public class ComnFileService { .append(name); } - result.append(this.FILE_EXTENSION); + result.append(extension.extension); return result.toString(); } @@ -68,7 +88,7 @@ public class ComnFileService { String airUser = model.getPilotName(); String etc = String.valueOf(System.currentTimeMillis()); // 동명이인 방지 - String fileName = getLaancSaveName(airUser, etc); + String fileName = getLaancSaveName(ExtensionConstant.PDF, airUser, etc); // TODO 추후 img tag의 src로 들어가는 이미지들을 base64로 변환하여 html에 넣어줘야함 // images 넣기(임시) @@ -102,12 +122,25 @@ public class ComnFileService { // DB Insert // ComFileBas lastComFileBas = comFileBasRepository.findFirstByOrderByFileSnoDesc(); - ComFileBas lastComFileBas = comFileBasRepository.findFirstByOrderByFileGroupNoDesc(); - int fileGroupNo = (lastComFileBas == null) ? 1 : lastComFileBas.getFileGroupNo() + 1; + int fileGroupNo = this.lastFileGroupNo(); comFileBas.setFileGroupNo(fileGroupNo); return comFileBasRepository.save(comFileBas); + } + + /** + * 다건 DB 인서트, 최신데이터 가져온 후 Group NO 1추가함 + * @param comFileBas + * @return + */ + public List saveAll(List comFileBas, Integer fileGroupNo){ + + for(ComFileBas fileBas : comFileBas){ + fileBas.setFileGroupNo(fileGroupNo); + } + + return comFileBasRepository.saveAll(comFileBas); } /** @@ -120,10 +153,146 @@ public class ComnFileService { ComFileBas comFileBas = comFileBasRepository.findById(fileSno).orElse(null); if (comFileBas == null) throw new CustomException(ErrorCode.DATA_NOTFIND); - pdfUtils.fileDownload(comFileBas); + InputStream inputStream = null; + OutputStream outputStream = null; + + try { + File pdfFile = new File(comFileBas.getFilePath() + comFileBas.getFileSaveNm()); + inputStream = new FileInputStream(pdfFile); + + String fileOriName = comFileBas.getFileOriNm(); + fileOriName = URLEncoder.encode(comFileBas.getFileOriNm(), StandardCharsets.UTF_8); + + response.setContentType("application/octet-stream"); + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-Disposition", "attachment; filename=\"" + fileOriName + "\""); + // response.setContentLengthLong(Long.parseLong(comFileBas.getFileSize())); + // response.setStatus(HttpServletResponse.SC_OK); + + outputStream = response.getOutputStream(); + + byte[] buffer = new byte[1024]; //1KB 설정 + int length; + + while ((length = inputStream.read(buffer)) != -1) { + outputStream.write(buffer); + } + + } catch (FileNotFoundException e) { + throw new CustomException(ErrorCode.DATA_NO); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (outputStream != null) { + Objects.requireNonNull(outputStream).flush(); + outputStream.close(); + } + + if (inputStream != null) { + inputStream.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + + } + + } + + public Integer fileUpload(List files, Integer fileGroupNo){ + + if(!this.validCheck(files)) throw new CustomException(ErrorCode.NON_VALID_PARAMETER); + if(fileGroupNo == null || fileGroupNo == 0) fileGroupNo = lastFileGroupNo(); + + // TODO : 절대경로 + String absPath = "/Users/igyeongdo/WokrSpace/"; + + String fileUrl = new StringBuilder() + .append(absPath) + .append(this.BASE_PATH) + .append(this.NORMAL_FORDER_PATH) + .append(InstantUtils.toDateStringByFormat(Instant.now(), "yyyyMMdd")) + .append("/") + .toString(); + + List comFileBas = new ArrayList<>(); + + for(MultipartFile file : files){ + String oriNm = file.getOriginalFilename(); + String extension = oriNm.substring(oriNm.lastIndexOf(".")); + String etc = String.valueOf(System.currentTimeMillis()); // 동명이인 방지 + String fileName = this.getLaancSaveName(ExtensionConstant.fromExtension(extension), fileGroupNo.toString(), "qna", etc); + + try { + Path directoryPath = Paths.get(fileUrl); + if (!Files.exists(directoryPath)) { + Files.createDirectories(directoryPath); + } + // 파일 저장 경로 + String filePath = fileUrl + fileName; + + File saveFile = new File(filePath); + file.transferTo(saveFile); + + long fileSize = Files.size(Paths.get(filePath)) / 1024; + + String userId = jwtTokenUtil.getUserIdByToken(); + if (userId == null) userId = "NONE"; + + ComFileBas node = new ComFileBas(); + node.setFileGroupNo(fileGroupNo); + node.setFilePath(fileUrl); + node.setFileExt(extension); + node.setCreateDt(Instant.now()); + node.setCreateUserId(userId); + node.setFileSaveNm(fileName); + node.setFileOriNm(oriNm); + node.setFileSize(String.valueOf(fileSize)); + + comFileBas.add(node); + } catch (IOException e) { + e.printStackTrace(); + } + } + + this.saveAll(comFileBas, fileGroupNo); + + return fileGroupNo; + } + + /** + * 정해진 확장자만 올 수 있도록 validation처리, + * TODO :: 혹시 mime 타입으로 확인하여 처리해야 할까요? + * @param files + * @return + */ + private boolean validCheck(List files){ + + for(MultipartFile file : files){ + + try { + String oriNm = file.getOriginalFilename(); + String extension = oriNm.substring(oriNm.lastIndexOf(".")); + + ExtensionConstant constants = ExtensionConstant.fromExtension(extension); + + // 허락된 확장자가 아닐 경우 return false + if(constants == null) return false; + + + } catch (Exception e) { + // 확장자가 없는 파일일 경우 return false; + return false; + } + + } + + return true; } + public String imagesToBase64ForSrc(String path) { StringBuilder str = new StringBuilder(); ClassPathResource resource = new ClassPathResource(path); @@ -147,6 +316,54 @@ public class ComnFileService { } return str.toString(); } + + /** + * 마지막 fileGroupNo 가져와 +1 후 반환 + * @return + */ + private Integer lastFileGroupNo(){ + ComFileBas lastComFileBas = comFileBasRepository.findFirstByOrderByFileGroupNoDesc(); + int fileGroupNo = (lastComFileBas == null) ? 1 : lastComFileBas.getFileGroupNo() + 1; + + return fileGroupNo; + } + + @Transactional + public boolean deleteFiles(int fileGroupNo){ + + List files = comFileBasRepository.findByFileGroupNoAndDelYn(fileGroupNo, "N"); + String userId = jwtTokenUtil.getUserIdByToken(); + + if (userId == null) userId = "NONE"; + + for(ComFileBas file : files){ + file.setDelYn("Y"); + file.setDelUserId(userId); + file.setDelDt(Instant.now()); + } + + comFileBasRepository.saveAll(files); + + return true; + } + + @Transactional + public boolean deleteFile(int fileSno){ + + ComFileBas file = comFileBasRepository.findByFileSnoAndDelYn(fileSno, "N"); + + String userId = jwtTokenUtil.getUserIdByToken(); + + if (userId == null) userId = "NONE"; + + file.setDelYn("Y"); + file.setDelUserId(userId); + file.setDelDt(Instant.now()); + + comFileBasRepository.save(file); + + return true; + } } diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/CnsFaqBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CnsFaqBas.java new file mode 100644 index 00000000..3cff6c40 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CnsFaqBas.java @@ -0,0 +1,53 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import java.time.Instant; + +import javax.persistence.*; + +import lombok.Data; + +@Entity +@Data +@Table(name="CNS_FAQ_BAS") +@NamedQuery(name="CnsFaqBas.findAll", query="SELECT c FROM CnsFaqBas c") +public class CnsFaqBas implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="FAQ_SNO") + private int faqSno; + + @Column(name="CATEGORY") + private String category; + + @Column(name="TITLE") + private String title; + + @Column(name="CONTENT") + private String content; + + @Column(name="VIEW_CNT") + private int viewCnt = 0; + + @Column(name="EXPSR_YN") + private String expsrYn = "N"; + + @Column(name="DEL_YN") + private String delYn = "N"; + + @Column(name="CREATE_USER_ID") + private String createUserId; + + @Column(name="CREATE_DT") + private Instant createDt; + + @Column(name="UPDATE_USER_ID") + private String updateUserId; + + @Column(name="UPDATE_DT") + private Instant updateDt; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/entity/CnsQnaBas.java b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CnsQnaBas.java new file mode 100644 index 00000000..b9fdaafe --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/entity/CnsQnaBas.java @@ -0,0 +1,60 @@ +package com.palnet.biz.jpa.entity; + +import java.io.Serializable; +import java.time.Instant; + +import javax.persistence.*; + +import lombok.Builder; +import lombok.Data; + +@Entity +@Data +@Table(name="CNS_QNA_BAS") +@NamedQuery(name="CnsQnaBas.findAll", query="SELECT c FROM CnsQnaBas c") +public class CnsQnaBas implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="QNA_SNO") + private int qnaSno; + + @Column(name="TARGET_SNO") + private int targetSno; + + @Column(name="CATEGORY") + private String category; + + @Column(name="TITLE") + private String title; + + @Column(name="CONTENT") + private String content; + + @Column(name="FILE_GROUP_NO") + private Integer fileGroupNo; + + @Column(name="EXPSR_YN") + private String expsrYn = "N"; + + @Column(name="DEL_YN") + private String delYn = "N"; + + @Column(name="VIEW_CNT") + private int viewCnt = 0; + + @Column(name="CREATE_USER_ID") + private String createUserId; + + @Column(name="CREATE_DT") + private Instant createDt; + + @Column(name="UPDATE_USER_ID") + private String updateUserId; + + @Column(name="UPDATE_DT") + private Instant updateDt; + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsFaqBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsFaqBasRepository.java new file mode 100644 index 00000000..ecf46ff3 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsFaqBasRepository.java @@ -0,0 +1,27 @@ +package com.palnet.biz.jpa.repository.cns; + +import javax.transaction.Transactional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.CnsFaqBas; + +@Repository +public interface CnsFaqBasRepository extends JpaRepository{ + + @Modifying + @Transactional + @Query("update CnsFaqBas c set c.viewCnt = c.viewCnt + 1" + + "where c.faqSno = :sno") + int updateViewCnt(@Param("sno") int sno); + + @Modifying + @Transactional + @Query("update CnsFaqBas c set c.delYn = 'Y' " + + "where c.faqSno = :sno") + int deleteFaq(@Param("sno") int sno); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsFaqQueryRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsFaqQueryRepository.java new file mode 100644 index 00000000..e3b092f1 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsFaqQueryRepository.java @@ -0,0 +1,111 @@ +package com.palnet.biz.jpa.repository.cns; + +import java.util.List; + +import org.springframework.stereotype.Repository; + +import com.palnet.biz.api.cns.faq.model.FaqListModel; +import com.palnet.biz.jpa.entity.QCnsFaqBas; +import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Repository +@RequiredArgsConstructor +public class CnsFaqQueryRepository { + + private final JPAQueryFactory query; + + public List getFaqList(String category, String word) { + + QCnsFaqBas bas = QCnsFaqBas.cnsFaqBas; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(bas.delYn.eq("N")); + builder.and(bas.expsrYn.eq("Y")); + + if(category != null) { + builder.and(bas.category.eq(category)); + } + + if(word != null) { + builder.and(bas.title.contains(word)); + } + + List r = query + .select(Projections.bean( + FaqListModel.class, + bas.faqSno, + bas.category, + bas.title, + bas.content, + bas.viewCnt, + bas.expsrYn, + bas.delYn, + bas.createUserId, + bas.createDt, + bas.updateUserId, + bas.updateDt + )) + .from(bas) + .where(builder) + .fetch(); + + + return r; + } + + public FaqListModel getFaqDetail(int sno) { + + QCnsFaqBas bas = QCnsFaqBas.cnsFaqBas; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(bas.faqSno.eq(sno)); + + FaqListModel r = query + .select(Projections.bean( + FaqListModel.class, + bas.faqSno, + bas.category, + bas.title, + bas.content, + bas.viewCnt, + bas.expsrYn, + bas.delYn, + bas.createUserId, + bas.createDt, + bas.updateUserId, + bas.updateDt + )) + .from(bas) + .where(builder) + .fetchOne(); + + + return r; + } + + public void updateFaq(FaqListModel model) { + QCnsFaqBas bas = QCnsFaqBas.cnsFaqBas; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(bas.faqSno.eq(model.getFaqSno())); + + query.update(bas) + .set(bas.category, model.getCategory()) + .set(bas.title, model.getTitle()) + .set(bas.content, model.getContent()) + .set(bas.viewCnt, model.getViewCnt()) + .set(bas.expsrYn, model.getExpsrYn()) + .set(bas.updateUserId, model.getUpdateUserId()) + .set(bas.updateDt, model.getUpdateDt()) + .where(builder) + .execute(); + + } + +} \ No newline at end of file diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaBasRepository.java new file mode 100644 index 00000000..9c569152 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaBasRepository.java @@ -0,0 +1,23 @@ +package com.palnet.biz.jpa.repository.cns; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import com.palnet.biz.jpa.entity.CnsQnaBas; + +@Repository +public interface CnsQnaBasRepository extends JpaRepository{ + + CnsQnaBas findFirstByTargetSnoAndDelYnAndExpsrYn(int targetSno, String delYn, String expsrYn); + + CnsQnaBas findByQnaSnoAndDelYnAndExpsrYn(int qnaSno, String delYn, String expsrYn); + + CnsQnaBas findFirstByQnaSnoAndTargetSnoAndDelYnAndExpsrYn(int qnaSno, int targetSno, String delYn, String expsrYn); + + @Modifying + @Query("UPDATE CnsQnaBas q SET q.viewCnt = q.viewCnt + 1 WHERE q.qnaSno = :qnaSno") + void pulsViewCount(@Param("qnaSno")int qnaSno); +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaQueryRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaQueryRepository.java new file mode 100644 index 00000000..32c787b0 --- /dev/null +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/cns/CnsQnaQueryRepository.java @@ -0,0 +1,69 @@ +package com.palnet.biz.jpa.repository.cns; + +import java.util.List; + +import org.springframework.stereotype.Repository; + +import com.palnet.biz.api.cns.qna.model.QnaBasModel; +import com.palnet.biz.jpa.entity.QCnsQnaBas; +import com.palnet.comn.code.ErrorCode; +import com.palnet.comn.exception.CustomException; +import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Repository +@RequiredArgsConstructor +public class CnsQnaQueryRepository { + + private final JPAQueryFactory query; + + /** + * 카테고리와 글로 게시글 검색, 만약 조건 없으면 전체검색 + * @param category + * @param word + * @return + */ + public List getQnaList(String category, String word) { + QCnsQnaBas bas = QCnsQnaBas.cnsQnaBas; + + BooleanBuilder builder = new BooleanBuilder(); + builder.and(bas.delYn.eq("N")); + builder.and(bas.expsrYn.eq("Y")); + + if(category != null) { + builder.and(bas.category.eq(category)); + } + + if(word != null) { + builder.and(bas.title.contains(word)); + } + + List r = query + .select(Projections.bean( + QnaBasModel.class, + bas.qnaSno, + bas.category, + bas.title, + bas.content, + bas.fileGroupNo, + bas.viewCnt, + bas.expsrYn, + bas.delYn, + bas.createUserId, + bas.createDt, + bas.updateUserId, + bas.updateDt + )) + .from(bas) + .where(builder) + .fetch(); + + return r; + } + +} diff --git a/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComFileBasRepository.java b/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComFileBasRepository.java index 0586623d..95a92c70 100644 --- a/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComFileBasRepository.java +++ b/pav-server/src/main/java/com/palnet/biz/jpa/repository/com/ComFileBasRepository.java @@ -1,5 +1,7 @@ package com.palnet.biz.jpa.repository.com; +import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -11,4 +13,9 @@ public interface ComFileBasRepository extends JpaRepository ComFileBas findFirstByOrderByFileSnoDesc(); ComFileBas findFirstByOrderByFileGroupNoDesc(); + + List findByFileGroupNoAndDelYn(int fileGroupNo, String delYn); + + ComFileBas findByFileSnoAndDelYn(int fileSno, String delYn); + } diff --git a/pav-server/src/main/java/com/palnet/comn/utils/PdfUtils.java b/pav-server/src/main/java/com/palnet/comn/utils/PdfUtils.java index 242c7a3c..55fd54d5 100644 --- a/pav-server/src/main/java/com/palnet/comn/utils/PdfUtils.java +++ b/pav-server/src/main/java/com/palnet/comn/utils/PdfUtils.java @@ -1,45 +1,43 @@ package com.palnet.comn.utils; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.Instant; +import java.util.Map; +import java.util.Map.Entry; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.context.Context; + import com.itextpdf.html2pdf.ConverterProperties; import com.itextpdf.html2pdf.HtmlConverter; import com.itextpdf.io.font.PdfEncodings; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfWriter; import com.itextpdf.layout.font.FontProvider; +import com.palnet.biz.api.comn.file.constant.ExtensionConstant; import com.palnet.biz.api.comn.file.model.PdfBaseModel; import com.palnet.biz.jpa.entity.ComFileBas; -import com.palnet.comn.code.ErrorCode; -import com.palnet.comn.exception.CustomException; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.thymeleaf.TemplateEngine; -import org.thymeleaf.context.Context; - -import javax.servlet.http.HttpServletResponse; -import java.io.*; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.time.Instant; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; @Slf4j @RequiredArgsConstructor @Component public class PdfUtils { - - private final HttpServletResponse response; + private final TemplateEngine templateEngine; - + @Value("${base-url}") private String BASE_PATH; - - private final String FILE_EXTENSION = ".pdf"; + + private final String PDF_FORDER_PATH = BASE_PATH + "od/"; /** @@ -80,7 +78,13 @@ public class PdfUtils { ComFileBas result = new ComFileBas(); - String pdfPath = this.BASE_PATH + InstantUtils.toDateStringByFormat(Instant.now(), "yyyyMMdd") + "/"; + String pdfPath = new StringBuilder() + .append(this.BASE_PATH) + .append(this.PDF_FORDER_PATH) + .append(InstantUtils.toDateStringByFormat(Instant.now(), "yyyyMMdd")) + .append("/") + .toString(); + String pdfFilePath = pdfPath + fileName; File path = new File(pdfPath); @@ -145,7 +149,7 @@ public class PdfUtils { result.setFileGroupNo(0); result.setFilePath(pdfPath); - result.setFileExt(this.FILE_EXTENSION); + result.setFileExt(ExtensionConstant.PDF.extension); result.setCreateDt(Instant.now()); result.setFileSaveNm(fileName); result.setFileOriNm(fileName); @@ -161,56 +165,5 @@ public class PdfUtils { return result; } - - /** - * 파일 Download - * - * @param comFileBas - */ - public void fileDownload(ComFileBas comFileBas) { - InputStream inputStream = null; - OutputStream outputStream = null; - - try { - File pdfFile = new File(comFileBas.getFilePath() + comFileBas.getFileSaveNm()); - inputStream = new FileInputStream(pdfFile); - - String fileOriName = comFileBas.getFileOriNm(); - fileOriName = URLEncoder.encode(comFileBas.getFileOriNm(), StandardCharsets.UTF_8); - - response.setContentType("application/octet-stream"); - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-Disposition", "attachment; filename=\"" + fileOriName + "\""); - // response.setContentLengthLong(Long.parseLong(comFileBas.getFileSize())); - // response.setStatus(HttpServletResponse.SC_OK); - - outputStream = response.getOutputStream(); - - byte[] buffer = new byte[1024]; //1KB 설정 - int length; - - while ((length = inputStream.read(buffer)) != -1) { - outputStream.write(buffer); - } - - } catch (FileNotFoundException e) { - throw new CustomException(ErrorCode.DATA_NO); - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - if (outputStream != null) { - Objects.requireNonNull(outputStream).flush(); - outputStream.close(); - } - - if (inputStream != null) { - inputStream.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - - } - } + }