feat: 공통 파일업로드 및 저장 적용

dev
Jonguk. Lim 6 months ago
parent 065336312d
commit e81513d248

@ -2,7 +2,7 @@
### swagger ### swagger
[API URL](http://localhost:8081/swagger-ui.html) [API URL](http://localhost:9076/swagger-ui.html)
### API 결과 수신 ### API 결과 수신

@ -35,6 +35,11 @@
<version>23.04.01-SNAPSHOT</version> <version>23.04.01-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>cokr.xit.base</groupId>
<artifactId>xit-file</artifactId>
<version>23.04.01-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>jakarta.xml.bind</groupId> <groupId>jakarta.xml.bind</groupId>

@ -5,6 +5,7 @@ import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -31,6 +32,9 @@ import cokr.xit.adds.inf.nims.model.NimsApiRequest;
import cokr.xit.adds.inf.nims.model.NimsApiRequest.BsshInfoReq; import cokr.xit.adds.inf.nims.model.NimsApiRequest.BsshInfoReq;
import cokr.xit.adds.inf.nims.model.NimsApiResult; import cokr.xit.adds.inf.nims.model.NimsApiResult;
import cokr.xit.adds.inf.nims.service.InfNimsService; import cokr.xit.adds.inf.nims.service.InfNimsService;
import cokr.xit.base.file.FileInfo;
import cokr.xit.base.file.service.FileService;
import cokr.xit.base.file.web.FileInfoFactory;
import cokr.xit.foundation.component.AbstractServiceBean; import cokr.xit.foundation.component.AbstractServiceBean;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -76,6 +80,7 @@ public class BizNimsServiceBean extends AbstractServiceBean implements BizNimsSe
private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
private final InfNimsService infNimsService; private final InfNimsService infNimsService;
private final BizNimsMapper bizNimsMapper; private final BizNimsMapper bizNimsMapper;
private final FileService fileService;
//------------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------
// NIMS API CALL // NIMS API CALL
@ -372,15 +377,18 @@ public class BizNimsServiceBean extends AbstractServiceBean implements BizNimsSe
if(bizNimsMapper.insertDsuseMgtReceipt(dto) == 1){ if(bizNimsMapper.insertDsuseMgtReceipt(dto) == 1){
int dtlCnt = 0; int dtlCnt = 0;
String dirPath = dsuseImgPath + Constants.FILE_DLMTR + dto.getDscdmngId();
File f = new File(dirPath);
if(!f.exists()) f.mkdirs();
for (BizNimsRequest.DsuseMgtDtl d : dtls) { for (BizNimsRequest.DsuseMgtDtl d : dtls) {
String sn = StringUtils.leftPad(dtlCnt + 1 + "", 3, "0");
d.setDscdmngId(dto.getDscdmngId()); d.setDscdmngId(dto.getDscdmngId());
d.setDscdmngSn(StringUtils.leftPad(dtlCnt + 1 + "", 3, "0")); d.setDscdmngSn(sn);
d.setRgtr(dto.getUserId()); d.setRgtr(dto.getUserId());
dtlCnt = dtlCnt + bizNimsMapper.insertDsuseMgtDtl(d); dtlCnt = dtlCnt + bizNimsMapper.insertDsuseMgtDtl(d);
// FIXME : file upload uploadFileAndSave("100", dto.getDscdmngId(), sn, files.get(dtlCnt-1), dirPath);
// files[dtlCnt].transferTo(new File("path"));
//d.setDsusePrdImgFile(null);
} }
if(dtls.size() != dtlCnt) throw ApiCustomException.create("폐기 관리 상세 등록 실패"); if(dtls.size() != dtlCnt) throw ApiCustomException.create("폐기 관리 상세 등록 실패");
} else { } else {
@ -401,27 +409,14 @@ public class BizNimsServiceBean extends AbstractServiceBean implements BizNimsSe
dto.setRgtr(dto.getUserId()); dto.setRgtr(dto.getUserId());
if(bizNimsMapper.updateDsuseMgtRslt(dto) == 1){ if(bizNimsMapper.updateDsuseMgtRslt(dto) == 1){
int dtlCnt = 0;
String dirPath = dsuseImgPath + Constants.FILE_DLMTR + dto.getDscdmngId(); String dirPath = dsuseImgPath + Constants.FILE_DLMTR + dto.getDscdmngId();
File f = new File(dirPath); File f = new File(dirPath);
if(!f.exists()) f.mkdirs(); if(!f.exists()) f.mkdirs();
int idx = 1;
for (MultipartFile mf : files) { for (MultipartFile mf : files) {
val name = mf.getOriginalFilename(); uploadFileAndSave("110", dto.getDscdmngId(), String.valueOf(idx), mf, dirPath);
val ext = name.substring(name.lastIndexOf(".")); idx++;
val filename = name.substring(0, name.lastIndexOf("."));
Path path = Paths.get(dirPath + Constants.FILE_DLMTR, name);
// FIXME : file upload
try {
mf.transferTo(path);
//FileCopyUtils.copy(mf.getInputStream(), Files.newOutputStream(path));
} catch (IOException e) {
throw ApiCustomException.create(String.format("폐기 통보[결과] 처리:파일 업로드 실패[%s]", e.getMessage()));
}
//d.setDsusePrdImgFile(null);
} }
} else { } else {
@ -884,36 +879,107 @@ public class BizNimsServiceBean extends AbstractServiceBean implements BizNimsSe
/** /**
* <pre> * <pre>
* set *
* (prmisnNo), (rprsntvNm) set * @param list List<NimsApiDto.ProductInfoKd>
* @param resList List<BizNimsResponse.DsuseMgtResponse>
* </pre> * </pre>
*/ */
private void setAddBsshInfo(List<BizNimsResponse.DsuseRptInfoRes> resList) { private void productInfoaddMnfSeqs(List<NimsApiDto.ProductInfoKd> list) {
for (BizNimsResponse.DsuseRptInfoRes r : resList) { String productCd = "";
r.setRptTyCdNm(Constants.RPT_TY_CD.getName(r.getRptTyCd()));
r.setDsuseSeCdNm(Constants.DSUSE_SE_CD.getName(r.getDsuseSeCd())); try {
r.setDsusePrvCdNm(Constants.DSUSE_PRV_CD.getName(r.getDsusePrvCd()));
r.setDsuseMthCdNm(Constants.DSUSE_MTH_CD.getName(r.getDsuseMthCd())); for (NimsApiDto.ProductInfoKd d : list) {
productCd = d.getPrductCd();
if (isEmpty(r.getPrmisnNo())) {
List<BsshInfoSt> list = saveBsshInfoSt( List<NimsApiDto.MnfSeqInfo> mnfList = getMnfSeqInfo(
BsshInfoReq.builder() NimsApiRequest.MnfSeqInfoReq.builder()
.fg("1") .fg("1")
.pg("1") .pg("1")
.bc(r.getBsshCd()) .p(d.getPrductCd())
.build() .build()
); );
if (isEmpty(list)) { d.getMnfSeqInfos().addAll(mnfList);
// FIXME : 데이타 정상 흐름 확인후 comment 제거
continue;
//throw ApiCustomException.create(String.format("데이타 오류(마약류취급자식별번호[%s]에 해당하는 데이타가 없습니다)", r.getBsshCd()));
}
r.setPrmisnNo(list.get(0).getPrmisnNo());
r.setRprsntvNm(list.get(0).getRprsntvNm());
} }
}
} }catch (Exception e){
if( e instanceof ApiCustomException){
throw ApiCustomException.create(String.format("[%s]의 제조번호 정보를 찾을수 없습니다.", productCd));
}
throw ApiCustomException.create(e.getMessage());
}
}
private void uploadFileAndSave(String infoType, String infoKey, String subType, MultipartFile mf, String dirPath) {
MultipartFile[] uploads = Arrays.asList(mf).toArray(new MultipartFile[0]);
List<FileInfo> files = (new FileInfoFactory()).makeFileInfos((new FileInfo.Relation()).setInfoType(infoType).setInfoKey(infoKey).setSubType(subType), uploads);
int affected = fileService.create(files);
val name = mf.getOriginalFilename();
val ext = name.substring(name.lastIndexOf("."));
val filename = name.substring(0, name.lastIndexOf("."));
Path path = Paths.get(dirPath + Constants.FILE_DLMTR, name);
// FIXME : file upload
try {
mf.transferTo(path);
//FileCopyUtils.copy(mf.getInputStream(), Files.newOutputStream(path));
} catch (IOException e) {
throw ApiCustomException.create(String.format("폐기 통보[결과] 처리:파일 업로드 실패[%s]", e.getMessage()));
}
}
/**
* <pre>
* set
* (prmisnNo), (rprsntvNm) set
* @param resList List<BizNimsResponse.DsuseMgtResponse>
* </pre>
*/
private void setAddBsshInfo(List<BizNimsResponse.DsuseRptInfoRes> resList) {
for (BizNimsResponse.DsuseRptInfoRes r : resList) {
r.setRptTyCdNm(Constants.RPT_TY_CD.getName(r.getRptTyCd()));
r.setDsuseSeCdNm(Constants.DSUSE_SE_CD.getName(r.getDsuseSeCd()));
r.setDsusePrvCdNm(Constants.DSUSE_PRV_CD.getName(r.getDsusePrvCd()));
r.setDsuseMthCdNm(Constants.DSUSE_MTH_CD.getName(r.getDsuseMthCd()));
if (isEmpty(r.getPrmisnNo())) {
List<BsshInfoSt> list = saveBsshInfoSt(
BsshInfoReq.builder()
.fg("1")
.pg("1")
.bc(r.getBsshCd())
.build()
);
if (isEmpty(list)) {
// FIXME : 데이타 정상 흐름 확인후 comment 제거
continue;
//throw ApiCustomException.create(String.format("데이타 오류(마약류취급자식별번호[%s]에 해당하는 데이타가 없습니다)", r.getBsshCd()));
}
r.setPrmisnNo(list.get(0).getPrmisnNo());
r.setRprsntvNm(list.get(0).getRprsntvNm());
}
}
}
/** /**
* <pre> * <pre>
@ -925,29 +991,29 @@ public class BizNimsServiceBean extends AbstractServiceBean implements BizNimsSe
*/ */
private void setAddProductInfo(List<NimsApiDto.DsuseRptInfoDtl> dtlList) { private void setAddProductInfo(List<NimsApiDto.DsuseRptInfoDtl> dtlList) {
for (NimsApiDto.DsuseRptInfoDtl r : dtlList) {//if() for (NimsApiDto.DsuseRptInfoDtl r : dtlList) {//if()
// 마약항정구분(nrcdSeNm), 중점일반구분(prtmSenm) // 마약항정구분(nrcdSeNm), 중점일반구분(prtmSenm)
if (isEmpty(r.getNrcdSeNm()) || isEmpty(r.getPrtmSeNm())) { if (isEmpty(r.getNrcdSeNm()) || isEmpty(r.getPrtmSeNm())) {
//NimsApiResult.Response<NimsApiDto.ProductInfoKd> result = infNimsService.getProductInfoKd( //NimsApiResult.Response<NimsApiDto.ProductInfoKd> result = infNimsService.getProductInfoKd(
List<NimsApiDto.ProductInfoKd> list = saveProductInfoKd( List<NimsApiDto.ProductInfoKd> list = saveProductInfoKd(
NimsApiRequest.ProductInfoReq.builder() NimsApiRequest.ProductInfoReq.builder()
.fg("1") .fg("1")
.pg("1") .pg("1")
.p(r.getPrductCd()) .p(r.getPrductCd())
.build(), .build(),
false false
); );
if (isEmpty(list)) { if (isEmpty(list)) {
// FIXME : 데이타 정상 흐름 확인후 comment 제거 // FIXME : 데이타 정상 흐름 확인후 comment 제거
continue; continue;
//throw ApiCustomException.create(String.format("데이타 오류(제품코드[%s]에 해당하는 데이타가 없습니다)", r.getPrductCd())); //throw ApiCustomException.create(String.format("데이타 오류(제품코드[%s]에 해당하는 데이타가 없습니다)", r.getPrductCd()));
} }
r.setNrcdSeNm(list.get(0).getNrcdSeNm()); r.setNrcdSeNm(list.get(0).getNrcdSeNm());
r.setPrtmSeNm(list.get(0).getPrtmSeNm()); r.setPrtmSeNm(list.get(0).getPrtmSeNm());
r.setStdPackngStleNm(list.get(0).getStdPackngStleNm()); r.setStdPackngStleNm(list.get(0).getStdPackngStleNm());
r.setPceCoUnitNm(list.get(0).getPceCoUnitNm()); r.setPceCoUnitNm(list.get(0).getPceCoUnitNm());
} }
// 제조수입자명(bsshNm) // 제조수입자명(bsshNm)
if (isEmpty(r.getBsshNm()) && !isEmpty(r.getBsshCd())) { if (isEmpty(r.getBsshNm()) && !isEmpty(r.getBsshCd())) {
@ -965,50 +1031,9 @@ public class BizNimsServiceBean extends AbstractServiceBean implements BizNimsSe
} }
r.setBsshNm(list.get(0).getBsshNm()); r.setBsshNm(list.get(0).getBsshNm());
} }
}
}
/**
* <pre>
*
* @param list List<NimsApiDto.ProductInfoKd>
* </pre>
*/
private void productInfoaddMnfSeqs(List<NimsApiDto.ProductInfoKd> list) {
String productCd = "";
try {
for (NimsApiDto.ProductInfoKd d : list) {
productCd = d.getPrductCd();
List<NimsApiDto.MnfSeqInfo> mnfList = getMnfSeqInfo(
NimsApiRequest.MnfSeqInfoReq.builder()
.fg("1")
.pg("1")
.p(d.getPrductCd())
.build()
);
d.getMnfSeqInfos().addAll(mnfList);
}
}catch (Exception e){
if( e instanceof ApiCustomException){
throw ApiCustomException.create(String.format("[%s]의 제조번호 정보를 찾을수 없습니다.", productCd));
}
throw ApiCustomException.create(e.getMessage());
} }
} }
// @Override // @Override
// public List<NimsApiDto.JurisdictionGovInfo> getJurisdictionGovInfo(NimsApiRequest.JurisdictionGovInfoRequest dto) { // public List<NimsApiDto.JurisdictionGovInfo> getJurisdictionGovInfo(NimsApiRequest.JurisdictionGovInfoRequest dto) {
// NimsApiResult.Response<NimsApiDto.JurisdictionGovInfo> result = infNimsService.getJurisdictionGovInfo(dto); // NimsApiResult.Response<NimsApiDto.JurisdictionGovInfo> result = infNimsService.getJurisdictionGovInfo(dto);

@ -0,0 +1,6 @@
package cokr.xit.base;
import org.springframework.stereotype.Controller;
@Controller
public class FileController extends cokr.xit.base.file.web.FileController {}

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cokr.xit.base.file.dao.FileMapper">
<resultMap id="fileRow" type="cokr.xit.base.file.FileInfo">
<result property="id" column="FILE_ID"/>
<result property="infoType" column="INF_TYPE"/>
<result property="infoKey" column="INF_KEY"/>
<result property="subType" column="SUB_TYPE"/>
<result property="name" column="FILE_NM"/>
<result property="path" column="FILE_PATH"/>
<result property="url" column="URL"/>
<result property="mimeType" column="MIME_TYPE"/>
<result property="size" column="FILE_SIZE"/>
<result property="downloadCount" column="DNLD_CNT"/>
<result property="sortOrder" column="SRT_ORD"/>
<result property="createdAt" column="REG_DT"/>
<result property="createdBy" column="RGTR"/>
<result property="useYN" column="USE_YN"/>
</resultMap>
<sql id="fileDirs">SELECT INF_TYPE
, CONCAT('d:/data/adds/files/', '2024050001', '/', DIR) DIR
FROM (
SELECT '00' INF_TYPE, 'attachment/' DIR FROM DUAL UNION
SELECT '01' INF_TYPE, 'document/' DIR FROM DUAL UNION
SELECT '02' INF_TYPE, 'article/' DIR FROM DUAL UNION
SELECT '100' INF_TYPE, '' DIR FROM DUAL UNION /* 폐기상품이미지 */
SELECT '110' INF_TYPE, '' DIR FROM DUAL UNION /* 폐기 이미지 */
SELECT '200' INF_TYPE, '' DIR FROM DUAL /* 폐기보고 문서 */
) FILE_DIRS</sql>
<sql id="selectFiles">
<if test="fileIDs != null">
SELECT A.*, FILE_PATH URL
FROM TB_FILE A
WHERE FILE_ID IN (<foreach collection="fileIDs" item="fileID" separator=",">#{fileID}</foreach>)
ORDER BY FILE_ID</if>
<if test="fileIDs == null"><include refid="utility.paging-prefix" />
SELECT A.*, FILE_PATH URL
FROM TB_FILE A
<where>
<if test="infoType != null"> AND A.INF_TYPE = #{infoType}</if>
<if test="infoKeys != null"> AND INF_KEY IN (<foreach collection="infoKeys" item="infoKey" separator=",">#{infoKey}</foreach>)</if>
AND USE_YN = 'Y'
</where>
<include refid="utility.orderBy" />
<include refid="utility.paging-suffix" /></if></sql>
<select id="getFileList" parameterType="map" resultType="dataobject">/* 파일 목록 조회(fileMapper.getFileList) */
<include refid="selectFiles" /></select>
<select id="getFilesOf" parameterType="map" resultMap="fileRow">/* 파일 가져오기(fileMapper.getFilesOf) */
<include refid="selectFiles" /></select>
<select id="getFiles" parameterType="map" resultMap="fileRow">/* 파일 가져오기(fileMapper.getFiles) */
<include refid="selectFiles" /></select>
<insert id="insertFile" parameterType="map">/* 파일 등록(fileMapper.insertFile) */
<selectKey keyProperty="file.id,file.path" keyColumn="NEW_ID,PATH" resultType="map" order="BEFORE">
SELECT NEW_ID, CONCAT(DIR, NEW_ID, '.', #{file.extension}) PATH
FROM (
SELECT NVL(MAX(FILE_ID) + 1, CONCAT(THIS_DAY, '00001')) NEW_ID
FROM TB_FILE A, (<include refid="utility.selectThisDay" />) B
WHERE FILE_ID LIKE CONCAT(THIS_DAY, '%')
) T1, (
<include refid="fileDirs" />
WHERE INF_TYPE = #{file.infoType}
) T2</selectKey>
INSERT INTO TB_FILE (
FILE_ID
, INF_TYPE
, INF_KEY
, SUB_TYPE
, FILE_NM
, FILE_PATH
, MIME_TYPE
, FILE_SIZE
, DNLD_CNT
, SRT_ORD
, RGTR
, REG_DT
, USE_YN
) VALUES (
#{file.id}
, #{file.infoType}
, #{file.infoKey}
, #{file.subType}
, #{file.name}
, #{file.path}
, #{file.mimeType}
, #{file.size}
, #{file.downloadCount}
, #{file.sortOrder}
, #{currentUser.id}
,<include refid="utility.now" />
, 'Y'
)
</insert>
<update id="reorder" parameterType="map">/* 파일 순서 변경(fileMapper.reorder) */
UPDATE TB_FILE SET
SRT_ORD = CASE FILE_ID
<foreach collection="fileIDs" item="fileID" index="index" separator=" ">WHEN #{fileID} THEN #{index}
</foreach>
ELSE SRT_ORD END
WHERE FILE_ID IN (<foreach collection="fileIDs" item="fileID" separator=",">#{fileID}</foreach>)</update>
<update id="updateDownloadCount" parameterType="map">/* 다운로드 횟수 증가(fileMapper.updateDownloadCount) */
UPDATE TB_FILE SET
DNLD_CNT = DNLD_CNT + 1
WHERE USE_YN = 'Y'
AND FILE_ID IN (<foreach collection="fileIDs" item="fileID" separator=",">#{fileID}</foreach>)</update>
<update id="removeFiles" parameterType="map">/* 파일 제거(fileMapper.removeFiles) */
UPDATE TB_FILE SET
USE_YN = 'N'
WHERE USE_YN = 'Y'
<if test="fileIDs != null"> AND FILE_ID IN (<foreach collection="fileIDs" item="fileID" separator=",">#{fileID}</foreach>)</if>
<if test="infoKeys != null">
AND INF_TYPE = #{infoType}
AND INF_KEY IN (<foreach collection="infoKeys" item="infoKey" separator=",">#{infoKey}</foreach>)</if></update>
<delete id="deleteFiles" parameterType="map">/* 파일 삭제(fileMapper.deleteFiles) */
DELETE FROM TB_FILE
<if test="fileIDs != null">WHERE FILE_ID IN (<foreach collection="fileIDs" item="fileID" separator=",">#{fileID}</foreach>)</if>
</delete>
</mapper>

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="utility">
<!-- For Maria DB -->
<sql id="paging-prefix"><if test="fetchSize != null and fetchSize &gt; 0">
SELECT QROWS.* FROM (
SELECT ROW_NUMBER() OVER(<include refid="utility.sortBy" />) ROW_NUM
, COUNT(*) OVER() TOT_CNT, QBODY.*
FROM (</if></sql>
<sql id="paging-suffix"><if test="fetchSize != null and fetchSize &gt; 0"> ) QBODY
) QROWS
WHERE ROW_NUM BETWEEN ((#{pageNum} - 1) * #{fetchSize}) + 1 AND (#{pageNum} * #{fetchSize})</if></sql>
<select id="foundRows" resultType="dataobject">/* 전체 결과수 가져오기(utility.foundRows) */
SELECT FOUND_ROWS() TOT_CNT</select>
<sql id="sortBy"><if test="orderBy != null and orderBy != ''">ORDER BY ${orderBy}</if></sql>
<sql id="orderBy"><if test="fetchSize == null or fetchSize &lt; 1"><include refid="utility.sortBy" /></if></sql>
<sql id="now"><if test="_databaseId == 'mariadb'">DATE_FORMAT(CURRENT_TIMESTAMP, '%Y%m%d%H%i%s')</if>
<if test="_databaseId == 'oracle'">TO_CHAR(CURRENT_TIMESTAMP, 'YYYYMMDDHH24MISS')</if></sql>
<sql id="selectNow">SELECT<include refid="utility.now" />NOW FROM DUAL</sql>
<sql id="today"><if test="_databaseId == 'mariadb'">DATE_FORMAT(CURRENT_DATE, '%Y%m%d')</if>
<if test="_databaseId == 'oracle'">TO_CHAR(CURRENT_DATE, 'YYYYMMDD')</if></sql>
<sql id="selectToday">SELECT<include refid="utility.today" />TODAY FROM DUAL</sql>
<sql id="thisDay">NVL(#{thisDay},<include refid="utility.today" />)</sql>
<sql id="selectThisDay">SELECT<include refid="utility.thisDay" />THIS_DAY FROM DUAL</sql>
</mapper>
Loading…
Cancel
Save