Spring文書の作成(ファイルを含む)
44864 ワード
package kr.or.ddit.cus.vo;
import java.util.Date;
import org.springframework.format.annotation.DateTimeFormat;
public class AttachFilesVO {
private String id;
private String uploadFileName;
private String uploadFileSize;
private int seq;
@DateTimeFormat(pattern ="yyyy-MM-dd")
private Date registDt;
@DateTimeFormat(pattern ="yyyy-MM-dd")
private Date updateDt;
private String registerId;
private String updaterId;
// getter,setter, toString 생략
}
CusVOpackage kr.or.ddit.cus.vo;
import java.util.Arrays;
import java.util.List;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.web.multipart.MultipartFile;
public class CusVO {
// 고객번호 CUS00001
private String cusNum;
@NotBlank
private String cusNm;
@NotBlank
private String pne;
@NotBlank
private String addr;
private String addr1;
private String addr2;
// 순번 추가 부탁
private int rnum;
// 다중 파일 객체
private MultipartFile[] uploadFile;
// 다중 파일 객체의 파일명
private String uploadFileName;
// 다중 파일 업로드 객체
private List<AttachFilesVO> attachFilesVO;
}
mapper.xml<!-- * selectKey?
일련번호 처리
마이바티스는 쿼리 실행 시 파라미터를 치환해줌
-->
<!-- 고객 등록 -->
<insert id="insert" parameterType="cusVO">
<!-- ******* -->
<selectKey order="BEFORE" keyProperty="cusNum" resultType="String">
SELECT 'CUS' || LPAD(NVL(MAX(SUBSTR(CUS_NUM,4)),0)+1,5,'0') FROM CUS
</selectKey>
INSERT INTO CUS(CUS_NUM,CUS_NM,ADDR,PNE)
VALUES(#{cusNum},#{cusNm},#{addr}|| ' ' || #{addr1} || ' ' || #{addr2}, #{pne})
</insert>
<!-- attach_files 테이블로 첨부파일 insert -->
<insert id="insertAttachFiles" parameterType="attachFilesVO">
<foreach collection="list" item="item" index="index"
open="INSERT ALL " separator=" " close="SELECT * FROM DUAL">
INTO ATTACH_FILES(ID,SEQ,UPLOAD_FILE_NAME,UPLOAD_FILE_SIZE,REGIST_DT,REGISTER_ID)
VALUES(#{item.id},#{item.seq},#{item.uploadFileName},#{item.uploadFileSize},SYSDATE,#{item.registerId})
</foreach>
</insert>
mapperpublic interface CusMapper {
public int insert(CusVO cusVO);
public int insertAttachFiles(List<AttachFilesVO> attachFilesVO);
}
serviceImplpackage kr.or.ddit.cus.service.impl;
@Service
public class CusServiceImpl implements CusService {
@Autowired
CusMapper cusMapper;
private static final Logger logger =
LoggerFactory.getLogger(CusServiceImpl.class);
//고객 등록
@Override
public int insert(CusVO cusVO) {
//cus 테이블로 insert
int result = cusMapper.insert(cusVO);
//업로드한 파일 객체들
MultipartFile[] uploadFile = cusVO.getUploadFile();
//파일 저장 경로 설정
String uploadFolder = "D:\\A_TeachingMaterial\\6.JspSpring\\workspace\\dasuriProj\\src\\main\\webapp\\resources\\upload";
//연/월/일 폴더 생성 시작-------
File uploadPath = new File(uploadFolder, getFolder());
logger.info("uploadPath : " + uploadPath);
if(uploadPath.exists()==false) {//해당 경로가 없으면 생성해줘야함
uploadPath.mkdirs();
}
//연/월/일 폴더 생성 끝-------
//업로드한 파일 객체들의 파일명과 크기 정보를 넣은 후 insert 할 리스트 객체
List<AttachFilesVO> attachFilesVO = new ArrayList<AttachFilesVO>();
int seq = 1;
//이미지 3개를 업로드 한다면 3회 반복
for(MultipartFile multipartFile : uploadFile) {
logger.info("-----------");
logger.info("파일명 : " + multipartFile.getOriginalFilename());
logger.info("파일크기 : " + multipartFile.getSize());
//각 파일 별로 세팅할 VO
AttachFilesVO vo = new AttachFilesVO();
//1) 파일id(기본키데이터), 파일시퀀스번호,파일명과 크기를 세팅
vo.setId(cusVO.getCusNum()); //고정값
vo.setSeq(seq++);
vo.setUploadFileSize(""+multipartFile.getSize());
vo.setRegisterId("admin");//로그인 한 아디디로 교체해야 함
//-----------UUID 파일명 처리 시작 ----------------------------
//동일한 이름으로 업로드되면 기존 파일을 지우게 되므로 이를 방지하기 위함
UUID uuid = UUID.randomUUID();
String uploadFileName = uuid.toString() + "-" + multipartFile.getOriginalFilename();
// c:\\upload\\gongu03.jpg으로 조립
// 이렇게 업로드 하겠다라고 설계 uploadFolder -> uploadPath
// /resources/upload/2022/02/21/asdfsadfsdafsda_test.jpg
vo.setUploadFileName("/resources/upload/" + getFolder() + "/" + uploadFileName);
File saveFile = new File(uploadPath,uploadFileName);
//-----------UUID 파일명 처리 끝 ----------------------------
try {
//transferTo() : 물리적으로 파일 업로드가 됨
multipartFile.transferTo(saveFile);
//-------썸네일 처리 시작---------
//이미지 파일인지 체킹
if(checkImageType(saveFile)) {
logger.info("이미지 파일? true");
//uploadPath : 연/월/일이 포함된 경로
//uploadFileName : UUID가 포함된 파일명
FileOutputStream thumbnail =
new FileOutputStream(
new File(uploadPath,"s_"+uploadFileName));
Thumbnailator.createThumbnail(multipartFile.getInputStream(),
thumbnail, 100, 100);
thumbnail.close();
}else {
logger.info("이미지 파일? false");
}
//-------썸네일 처리 끝---------
//파일 실제 명을 list에 담음
attachFilesVO.add(vo);
}catch(Exception e){
logger.info(e.getMessage());
}//end catch
}
//attach_files 테이블로 insert
int filesResult = cusMapper.insertAttachFiles(attachFilesVO);
return result;
}
//첨부파일을 보관하는 폴더를 연/월/일 계층 형태로 생성하기 위함
private String getFolder() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
String str = sdf.format(date);
return str.replace("-", "/");
}
//특정한 파일이 이미지 타입인지 검사해주는 메소드
private boolean checkImageType(File file) {
try {
//file.toPath() : 파일의 전체 경로
logger.info("file.toPath() : " + file.toPath());
String contentType = Files.probeContentType(file.toPath());
logger.info("contentType : " + contentType);
//contentType이 image로 시작하면 이미지 타입이므로 true를 리턴함
return contentType.startsWith("image");
}catch(IOException e) {
e.printStackTrace();
}
return false;
}
}
controllerpackage kr.or.ddit.cus.controller;
@RequestMapping("/cus")
@Controller
public class CusController {
private static final Logger logger =
LoggerFactory.getLogger(CusController.class);
@Autowired
CusService cusService;
@GetMapping("/insert")
public String insert(Model model) {
Map<String,String> pageHeader = new HashMap<String, String>();
pageHeader.put("subtitle", "Customer");
pageHeader.put("title", "고객 등록");
model.addAttribute("pageHeader", pageHeader);
model.addAttribute("cusVO", new CusVO());
//forwarding
return "cus/insert";
}
// form의 입력값들이 CusVO에 매핑됨 메모리에 올라와있는 cusVO의 검증결과가 BindingResult에 들어감
@PostMapping("/insert")
public String insertPost(@Validated CusVO cusVO, BindingResult result) {
// 검증 오류 발생시
if(result.hasErrors()) {
List<ObjectError> allErrors = result.getAllErrors();
List<ObjectError> globalErrors = result.getGlobalErrors();
List<FieldError> fieldErrors = result.getFieldErrors();
//validation 중에 어떤 오류가 나왔는지 확인..
for(int i=0;i<allErrors.size();i++) {
ObjectError objectError = allErrors.get(i);
logger.info("objectError : " + objectError);
}
for(ObjectError objectError : globalErrors) {
logger.info("objectError : " + objectError);
}
for(FieldError fieldError : fieldErrors) {
logger.info("fieldError : " + fieldError.getDefaultMessage());
}
// redirect(x) => 데이터를 보낼 수 없음
// forwarding
return "cus/insert";
}
// insert 처리
logger.info("cusVO: " + cusVO.toString());
int insertResult = cusService.insert(cusVO);
if(insertResult>0) { //고객 등록 성공
// 목록으로 이동
return "redirect:/cus/list";
}else {
return "cus/insert";
}
}
VIEW(jsp)<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<script type="text/javascript" src="/resources/js/jquery-3.6.0.js"></script>
<form:form modelAttribute="cusVO" method="post" action="/cus/insert" enctype="multipart/form-data">
<ul class="list-group list-group-flush">
<li class="list-group-item p-3">
<div class="row">
<div class="col-sm-12 col-md-6">
<strong class="text-muted d-block mb-2">고객 이름</strong>
<div class="form-group">
<form:input path="cusNm" class="form-control" />
<font color="red" style="font-size:8pt;">
<form:errors path="cusNm" />
</font>
</div>
<strong class="text-muted d-block mb-2">연락처</strong>
<div class="form-group">
<form:input path="pne" class="form-control" />
<font color="red" style="font-size:8pt;">
<form:errors path="pne" />
</font>
</div>
<strong class="text-muted d-block mb-2">고객 주소</strong>
<div class="form-row">
<div class="form-group col-md-7">
<form:input path="addr" class="form-control" />
<font color="red" style="font-size:8pt;">
<form:errors path="addr" />
</font>
</div>
<div class="form-group col-md-5">
<button type="button" class="mb-2 btn btn-sm btn-info mr-1"
onclick="openHomeSearch()">우편번호 검색</button>
</div>
</div>
<div class="form-group">
<input type="text" class="form-control" name="addr1" id="addr1" placeholder="" />
</div>
<div class="form-group">
<input type="text" class="form-control" name="addr2" id="addr2" placeholder="" />
</div>
<div class="form-group" style="float:right;">
<button type="submit" class="mb-2 btn btn-sm btn-success mr-1">등록</button>
<button type="reset" class="mb-2 btn btn-sm btn-danger mr-1">취소</button>
</div>
</div>
<div class="col-sm-12 col-md-6">
<strong class="text-muted d-block mb-2">고객 이미지</strong>
<div class="form-group">
<div class="imgs_wrap"></div>
</div>
<div class="form-group">
<input type="file" id="input_imgs" name="uploadFile" multiple />
</div>
</div>
</div>
</li>
</ul>
</form:form>
<script type="text/javascript">
$(function(){
$("#input_imgs").on("change",handleImgsFilesSelect);
});
//e : change이벤트를 받음
function handleImgsFilesSelect(e){
//이벤트가 일어난 파일객체의 이미지 파일들을 가져옴
var files = e.target.files;
//파일들을 배열로 만들어 관리
var filesArr = Array.prototype.slice.call(files);
//f : 각각의 파일 객체
filesArr.forEach(function(f){
if(!f.type.match("image.*")){
alert("이미지만 가능합니다.");
//업로드 종료(실패)
return;
}
//각 이미지를 reader로 읽어들임
var reader = new FileReader();
reader.onload = function(e){
var img_html = "<img src=\"" + e.target.result + "\" style='width:100px;' />";
$(".imgs_wrap").append(img_html);
}
reader.readAsDataURL(f);
});//end forEach
}
</script>
Reference
この問題について(Spring文書の作成(ファイルを含む)), 我々は、より多くの情報をここで見つけました https://velog.io/@vgo_dongv/Spring-글작성파일포함テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol