데일리로그C:
article thumbnail
Published 2023. 5. 8. 14:12
스프링 첨부파일 구현 JAVA/spring

첨부파일 - project: ex03

 

1. UUID 랜덤값으로 첨부파일 생성

 

1) pom.xml --> 추가

<bash />
<!-- 첨부파일 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> <!-- 썸네일 --> <dependency> <groupId>org.imgscalr</groupId> <artifactId>imgscalr-lib</artifactId> <version>4.2</version> </dependency> <!-- @Resource 인식 --> <dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </dependency>

 

2) resources 에 upload 폴더 생성

 

3) servlet-context.xml --> 추가

  ㄴ> upload 폴더 경로 확인할 것(c드라이브 -> spring -> ....)

<bash />
<!-- 첨부파일 용량 제한 및 경로 --> <beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <beans:property name="maxUploadSize" value="10485760"></beans:property> </beans:bean> <beans:bean id="uploadPath" class="java.lang.String"> <beans:constructor-arg value="C:\\spring\\ex03\\src\\main\\webapp\\resources\\upload"></beans:constructor-arg> </beans:bean>

 

4) UploadControllerA.java 

<bash />
package org.zerock.controller; import java.io.File; import java.util.UUID; import javax.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.util.FileCopyUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.support.RedirectAttributes; @Controller public class UploadControllerA { private static final Logger logger = LoggerFactory.getLogger(UploadControllerA.class); // 첨부파일 저장 경로 @Resource(name = "uploadPath") // servlet-context.xml에 있는 bean id="uploadPath" 경로 매칭 private String uploadPath; @RequestMapping(value = "/uploadForm", method = RequestMethod.GET) public void uploadFormGet() { // void이므로 uploadForm.jsp forward } //한글 파일 이름이 깨진다면 web.xml에 한글 처리용 필터를 적용 @RequestMapping(value = "/uploadForm", method = RequestMethod.POST) public String uploadFormPost(MultipartFile file, RedirectAttributes rttr) throws Exception { logger.info("originalName: " + file.getOriginalFilename()); logger.info("size: " + file.getSize()); //byte 단위 logger.info("contentType: " + file.getContentType()); String savedName = uploadFile(file.getOriginalFilename(), file.getBytes()); rttr.addFlashAttribute("savedName",savedName); return "redirect:/uploadForm"; } // UUID 중복되지 않는 고유한 키 값을 설정할 때 사용 // uploadFile()은 원본 파일의 이름과 파일 데이터를 byte[]로 변환한 정보를 파라미터로 처리해서 실제로 파일 업로드한다. private String uploadFile(String originalName, byte[] fileData) throws Exception { UUID uid = UUID.randomUUID(); String savedName = uid.toString() + "_" + originalName; // import java.io.File; File target = new File(uploadPath, savedName); // FileCopyUtils는 'org.springframework.util' 패키지에 설정된 클래스(실제 파일 처리) FileCopyUtils.copy(fileData, target); return savedName; } }

 

5) uploadForm.jsp

<bash />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ include file="/WEB-INF/views/include/header.jsp" %> <hr> <form method="post" enctype="multipart/form-data"> <input multiple="multiple" type="file" name='file'> <!-- spring에서는 input에 multiple="multiple" 필수로 적어야함 --> <input type='submit' value="확인"> </form> <hr> 업로드 성공 파일명 : ${savedName } </body> </html>

 

6) header.jsp --> 추가

<bash />
<a href="/uploadAjax">[uploadAjax]</a> <a href="/uploadForm2">[uploadForm2]</a> <a href="/uploadForm">[uploadForm]</a>

 

 

 

2. 년월일시분초로 생성

1) UploadControllerB.java

<bash />
package org.zerock.controller; import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; import javax.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.util.FileCopyUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.multipart.MultipartFile; @Controller public class UploadControllerB { private static final Logger logger = LoggerFactory.getLogger(UploadControllerB.class); // 첨부파일 저장 경로 // servlet-context.xml에 있는 bean id="uploadPath" 경로 매칭 @Resource(name = "uploadPath") private String uploadPath; @RequestMapping(value = "/uploadForm2", method = RequestMethod.GET) public void uploadFormGet() { logger.info("============= uploadForm2 : get ================"); } //한글 파일 이름이 깨진다면 web.xml에 한글 처리용 필터를 적용 @RequestMapping(value = "/uploadForm2", method = RequestMethod.POST) public String uploadFormPost(MultipartFile[] file, Model model) throws Exception { logger.info("============= uploadForm2 : post ================"); logger.info("============= file.length ====:"+file.length); String savedName[] = new String[file.length]; //저장 파일명 배열 처리 for(int i=0; i<file.length; i++) { if(file[i].getSize() > 0) { //파일크기가 0보다 크다면 : 파일 유무 (처리안하면 안올렸을 때도 이상한 이미지 들어감) logger.info("originalName: " + file[i].getOriginalFilename()); logger.info("size: " + file[i].getSize()); //byte 단위 logger.info("contentType: " + file[i].getContentType()); Date today = new Date(); SimpleDateFormat cal = new SimpleDateFormat("yyyyMMddhhmmss"); String signdate = cal.format(today); savedName[i] = signdate + "_" + file[i].getOriginalFilename(); //날짜_파일명 처리 byte[] fileData = file[i].getBytes(); logger.info("============= savedName["+i+"] ====:"+savedName[i]); File target = new File(uploadPath, savedName[i]); FileCopyUtils.copy(fileData, target); //파일 업로드 } } return "redirect:/uploadForm2"; } }

 

2) uploadForm2.jsp

<bash />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ include file="/WEB-INF/views/include/header.jsp" %> <hr> <form method="post" enctype="multipart/form-data"> <input multiple="multiple" type='file' name='file'> <!-- name은 동일하게 file로! --> <input multiple="multiple" type='file' name='file'> <input type='submit' value="확인"> </form> <hr> </body> </html>

 

 

3. 썸네일 구현

1) UploadControllerB.java --> 추가

<bash />
//복사 붙여넣기 하자 (썸네일 import 세개) import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; // 첫 이미지 썸네일 if(i == 0) { String new_name = "thum_" + savedName[0]; //썸네일 파일 이름 //사이즈 크기 int w = 50; int h = 50; String imgFormat = "jpg"; //기본 설정 초기화 Image image = ImageIO.read(new File(uploadPath+"\\"+savedName[0])); //원본 이미지 if(image != null) { //이미지 파일이 아닌 경우 null Image resizeImage = image.getScaledInstance(w,h,Image.SCALE_SMOOTH); BufferedImage newImage = new BufferedImage(w,h,BufferedImage.TYPE_INT_BGR); Graphics g = newImage.getGraphics(); g.drawImage(resizeImage, 0, 0, null); g.dispose(); ImageIO.write(newImage, imgFormat, new File(uploadPath+"\\"+new_name)); //파일 올리기 } }

 

 

4. ajax 이용

  ㄴ> js로 유효성 검사 하기(이미지 파일을 올렸는지 다른 파일인지)

  ㄴ> restcontroller

  ㄴ> controller 사용 -- @ResponseBody 필요

 

1) UploadController.java

<bash />
package org.zerock.controller; import java.io.File; import java.util.UUID; import javax.annotation.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.util.FileCopyUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; @Controller public class UploadController { private static final Logger logger = LoggerFactory.getLogger(UploadController.class); // 첨부파일 저장 경로 // servlet-context.xml에 있는 bean id="uploadPath" 경로 매칭 @Resource(name = "uploadPath") private String uploadPath; @RequestMapping(value = "/uploadAjax", method = RequestMethod.GET) public void uploadAjax() { } // @ResponseBody : 요청이 온 데이터(JSON, XML)가 그대로 전송될 것임을 명시한다. @ResponseBody @RequestMapping(value ="/uploadAjax", method=RequestMethod.POST, produces = "text/plain;charset=UTF-8") public ResponseEntity<String> uploadAjax(MultipartFile file) throws Exception{ logger.info("originalName: " + file.getOriginalFilename()); logger.info("size: " + file.getSize()); logger.info("contentType: " + file.getContentType()); return new ResponseEntity<>(file.getOriginalFilename(),HttpStatus.CREATED); // HttpStatus.OK, HttpStatus.CREATED 정상적으로 생성되었다는 상태 코드 } // UUID 중복되지 않는 고유한 키 값을 설정할 때 사용 // uploadFile()은 원본 파일의 이름과 파일 데이터를 byte[]로 변환한 정보를 파라미터로 처리해서 실제로 파일 업로드한다. private String uploadFile(String originalName, byte[] fileData) throws Exception { UUID uid = UUID.randomUUID(); String savedName = uid.toString() + "_" + originalName; File target = new File(uploadPath, savedName); // FileCopyUtils는 'org.springframework.util' 패키지에 설정된 클래스(실제 파일 처리) FileCopyUtils.copy(fileData, target); return savedName; } }

 

2) uploadAjax.jsp

<bash />
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <style> .fileDrop { width: 100%; height: 200px; border: 1px dotted blue; } small { margin-left: 3px; font-weight: bold; color: gray; } </style> <script src="http://code.jquery.com/jquery-1.12.4.min.js"></script> <script src="http://code.jquery.com/jquery-migrate-1.4.1.min.js"></script> <h3>Ajax File Upload</h3> <!-- 파일을 Drop and Down 영역 --> <div class='fileDrop'></div> <div class='uploadedList'></div> <script> $(".fileDrop").on("dragenter dragover", function(event) { // 이벤트 처리를 제한한다. // 파일을 영역에 끌어다 놓아도 아무런 변화가 없게 처리 event.preventDefault(); }); $(".fileDrop").on("drop", function(event){ event.preventDefault(); // event.originalEvent : 전달된 파일 데이터를 가져오는 부분 // event.dataTransfer : 이벤트와 같이 전돨된 데이터를 의미하고, // 그 안에 포함된 파일 데이터를 찾아내기 위해서 dataTransfer.files를 이용한다. var files = event.originalEvent.dataTransfer.files; var file = files[0]; console.log(file); // formData : <form> 태그로 만든 데이터 전송 방식과 동일하게 데이터를 전송할 수 있다. var formData = new FormData(); formData.append("file", file); // 파일 객체를 추가 // 파일 데이터를 전송하기 위해서 processData, contentType 두 옵션을 반드시 false 지정 // 두개의 옵션은 데이터 전송을 <form> 태그를 이용하는 파일 업로드와 동일하게 해주는 역활 $.ajax({ url: '/uploadAjax', data: formData, dataType:'text', processData: false, contentType: false, type: 'POST', success: function(data){ alert(data); } }); }); </script> </body> </html>

 

3) package 생성  --> org.zerock.util

(1) UploadFileUtils.java

<bash />
package org.zerock.util; import java.io.File; import java.text.DecimalFormat; import java.util.Calendar; import java.util.UUID; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import org.imgscalr.Scalr; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.FileCopyUtils; public class UploadFileUtils { private static final Logger logger = LoggerFactory.getLogger(UploadFileUtils.class); // 파일 업로드 (저장 경로,원본 파일 이름,파일 데이터) 필요 요소 세가지 public static String uploadFile(String uploadPath, String originalName, byte[] fileData) throws Exception{ UUID uid = UUID.randomUUID(); String savedName = uid.toString() +"_"+originalName; //파일명 리네임 String savedPath = calcPath(uploadPath); //날짜별 폴더 생성 및 경로 설정(아래 메서드 참조) File target = new File(uploadPath +savedPath,savedName); FileCopyUtils.copy(fileData, target); //임시 폴더에 업로드된 파일을 지정 폴더로 복사 String formatName = originalName.substring(originalName.lastIndexOf(".")+1); //확장자 String uploadedFileName = null; if(MediaUtils.getMediaType(formatName) != null){ //이미지 관련 확장자 uploadedFileName = makeThumbnail(uploadPath, savedPath, savedName); }else{ uploadedFileName = makeIcon(uploadPath, savedPath, savedName); } return uploadedFileName; } // 이미지 타입의 파일이 아닌 경우 실행 문자열의 치환 용도에 불과 private static String makeIcon(String uploadPath, String path, String fileName)throws Exception{ String iconName = uploadPath + path + File.separator+ fileName; return iconName.substring(uploadPath.length()).replace(File.separatorChar, '/'); } // 썸네일 생성 private static String makeThumbnail(String uploadPath, String path, String fileName) throws Exception{ BufferedImage sourceImg = ImageIO.read(new File(uploadPath + path, fileName)); BufferedImage destImg = Scalr.resize(sourceImg, Scalr.Method.AUTOMATIC, Scalr.Mode.FIT_TO_HEIGHT,100); String thumbnailName = uploadPath + path + File.separator +"s_"+ fileName; File newFile = new File(thumbnailName); String formatName = fileName.substring(fileName.lastIndexOf(".")+1); ImageIO.write(destImg, formatName.toUpperCase(), newFile); return thumbnailName.substring(uploadPath.length()).replace(File.separatorChar, '/'); } // 년/월/일 폴더 생성,파일저장 // 작성된 calcPath()의 리턴 값은 최종 결과 폴더를 반환하는데, // 내부적으로 폴더를 생성해 주는 기능이 필요하기 때문에 기본적인 경로 uploadPath를 파라미터로 전달 받는다. private static String calcPath(String uploadPath){ Calendar cal = Calendar.getInstance(); String yearPath = File.separator+cal.get(Calendar.YEAR); String monthPath = yearPath + File.separator + new DecimalFormat("00").format(cal.get(Calendar.MONTH)+1); String datePath = monthPath + File.separator + new DecimalFormat("00").format(cal.get(Calendar.DATE)); // 얻어낸 날짜 정보는 기본 경로롸 함께 makeDir()에 전달되어 폴더 생성된다. makeDir(uploadPath,yearPath,monthPath,datePath); logger.info(datePath); return datePath; } //폴더 생성 private static void makeDir(String uploadPath, String... paths){ if(new File(uploadPath + paths[paths.length-1]).exists()){ return; } for (String path : paths) { File dirPath = new File(uploadPath + path); if(! dirPath.exists() ){ dirPath.mkdir(); } } } }

 

(2) MediaUtils.java

<bash />
package org.zerock.util; import java.util.HashMap; import java.util.Map; import org.springframework.http.MediaType; public class MediaUtils { private static Map<String, MediaType> mediaMap; static{ mediaMap = new HashMap<String, MediaType>(); mediaMap.put("JPG", MediaType.IMAGE_JPEG); mediaMap.put("GIF", MediaType.IMAGE_GIF); mediaMap.put("PNG", MediaType.IMAGE_PNG); } public static MediaType getMediaType(String type){ return mediaMap.get(type.toUpperCase()); // toUpperCase() 대문자로 변경 } }

 

6) UploadController.java --> 수정 & 추가

<bash />
@ResponseBody 부분 //return new ResponseEntity<>(file.getOriginalFilename(),HttpStatus.CREATED); // HttpStatus.OK, HttpStatus.CREATED 정상적으로 생성되었다는 상태 코드 return new ResponseEntity<>( UploadFileUtils.uploadFile(uploadPath, file.getOriginalFilename(), file.getBytes()), HttpStatus.CREATED);

 

7) UploadController.java --> 추가

<bash />
// 파일 화면 출력 부분 @ResponseBody @RequestMapping("/displayFile") public ResponseEntity<byte[]> displayFile(String fileName)throws Exception{ InputStream in = null; ResponseEntity<byte[]> entity = null; logger.info("FILE NAME: " + fileName); try{ String formatName = fileName.substring(fileName.lastIndexOf(".")+1); MediaType mType = MediaUtils.getMediaType(formatName); HttpHeaders headers = new HttpHeaders(); in = new FileInputStream(uploadPath+fileName); if(mType != null){ headers.setContentType(mType); }else{ fileName = fileName.substring(fileName.indexOf("_")+1); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.add("Content-Disposition", "attachment; filename=\""+ new String(fileName.getBytes("UTF-8"), "ISO-8859-1")+"\""); } entity = new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED); }catch(Exception e){ e.printStackTrace(); entity = new ResponseEntity<byte[]>(HttpStatus.BAD_REQUEST); }finally{ in.close(); } return entity; } // 첨부파일 삭제 @ResponseBody @RequestMapping(value = "/deleteFile", method=RequestMethod.POST) public ResponseEntity<String> deleteFile(String fileName){ logger.info("delete file: " + fileName); String formatName = fileName.substring(fileName.lastIndexOf(".")+1); MediaType mType = MediaUtils.getMediaType(formatName); if(mType != null) { String front = fileName.substring(0, 12); String end = fileName.substring(14); new File(uploadPath + (front + end).replace('/', File.separatorChar)).delete(); } new File(uploadPath + fileName.replace('/', File.separatorChar)).delete(); return new ResponseEntity<String>("deleted", HttpStatus.OK); }

 

8) uploadAjax.jsp --> 추가

<bash />
수정 //alert(data); //추가 페이지 var str =""; if(checkImageType(data)){ str ="<div><a href=displayFile?fileName="+getImageLink(data)+">" +"<img src='displayFile?fileName="+data+"'/>" +"</a><small data-src="+data+">X</small></div>"; }else{ str = "<div><a href='displayFile?fileName="+data+"'>" + getOriginalName(data)+"</a>" +"<small data-src="+data+">X</small></div></div>"; } $(".uploadedList").append(str); 추가 //파일 삭제 $(".uploadedList").on("click", "small", function(event){ var that = $(this); $.ajax({ url:"deleteFile", type:"post", data: {fileName:$(this).attr("data-src")}, dataType:"text", success:function(result){ if(result == 'deleted'){ that.parent("div").remove(); //화면에서 삭제처리 } } }); }); <script> // 파일 첨부시 이름만 뽑아오는 코드 function getOriginalName(fileName){ if(checkImageType(fileName)){ return; } var idx = fileName.indexOf("_") + 1 ; return fileName.substr(idx); } function getImageLink(fileName){ if(!checkImageType(fileName)){ return; } var front = fileName.substr(0,12); //년,월,일 경로 추출하는 용도 var end = fileName.substr(14); //파일 이름 앞의 's_'까지의 값 return front + end; //'s_'값을 제외한 결과 값 } //전송 문자열이 이미지 파일인지 확인 여부 function checkImageType(fileName){ var pattern = /jpg|gif|png|jpeg/i; return fileName.match(pattern); } </script>

 

 

5. 트랜잭션

1) pom.xml

<bash />
<!-- 트랜잭션 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${org.springframework-version}</version> </dependency>

 

2) root-context.xml

(1) namespaces에서 tx 활성화하기

(2) 추가

<bash />
<!-- 트랜젝션 처리 추가 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <tx:annotation-driven />

 

3) 첨부파일 table 생성

<bash />
create table tbl_attach ( fullName varchar(150) not null, // 이름 bno int not null, // 부모값 regdate timestamp default now(), // 생성일 primary key(fullName) );

 

4) BoardVO.java --> 추가

<bash />
private String[] files;

 

5) BoardDAO.java --> 추가

<bash />
public void addAttach(String fullName) throws Exception; //첨부파일 추가

 

6) BoardDAOImpl.java --> 추가

<bash />
@Override public void addAttach(String fullName) throws Exception { session.insert(namespace+".addAttach",fullName); }

 

7) boardMapper.xml --> 추가

<bash />
<insert id="addAttach"> insert into tbl_attach (fullName, bno) values (#{fullName},LAST_INSERT_ID()) </insert>

 

8) BoardServiceImpl.java --> regist 수정

<bash />
@Transactional @Override public void regist(BoardVO board) throws Exception { dao.create(board); //파일첨부 String[] files = board.getFiles(); if(files == null) { return; } for(String fileName : files) { dao.addAttach(fileName); } }

 

9) UploadSboardController.java

<bash />
package org.zerock.controller; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import javax.annotation.Resource; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import org.zerock.util.MediaUtils; import org.zerock.util.UploadFileUtils; @Controller @RequestMapping("/sboard/") public class UploadSboardController { private static final Logger logger = LoggerFactory.getLogger(UploadSboardController.class); @Resource(name = "uploadPath") private String uploadPath; @RequestMapping(value = "/uploadAjax", method = RequestMethod.GET) public void uploadAjax() { } // @ResponseBody : 요청이 온 데이터(JSON, XML)가 그대로 전송될 것임을 명시한다. @ResponseBody @RequestMapping(value ="/uploadAjax", method=RequestMethod.POST, produces="text/plain;charset=UTF-8") public ResponseEntity<String> uploadAjax(MultipartFile file) throws Exception{ logger.info("originalName: " + file.getOriginalFilename()); logger.info("size: " + file.getSize()); logger.info("contentType: " + file.getContentType()); //return new ResponseEntity<>(file.getOriginalFilename(),HttpStatus.CREATED); // HttpStatus.OK, HttpStatus.CREATED 정상적으로 생성되었다는 상태 코드 return new ResponseEntity<String>( UploadFileUtils.uploadFile(uploadPath, file.getOriginalFilename(), file.getBytes()), HttpStatus.CREATED); } // 파일 화면 출력 부분 @ResponseBody @RequestMapping("/displayFile") public ResponseEntity<byte[]> displayFile(String fileName)throws Exception{ InputStream in = null; ResponseEntity<byte[]> entity = null; logger.info("FILE NAME: " + fileName); try{ String formatName = fileName.substring(fileName.lastIndexOf(".")+1); MediaType mType = MediaUtils.getMediaType(formatName); HttpHeaders headers = new HttpHeaders(); in = new FileInputStream(uploadPath+fileName); if(mType != null){ headers.setContentType(mType); }else{ fileName = fileName.substring(fileName.indexOf("_")+1); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.add("Content-Disposition", "attachment; filename=\""+ new String(fileName.getBytes("UTF-8"), "ISO-8859-1")+"\""); } entity = new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED); }catch(Exception e){ e.printStackTrace(); entity = new ResponseEntity<byte[]>(HttpStatus.BAD_REQUEST); }finally{ in.close(); } return entity; } // 첨부파일 삭제 @ResponseBody @RequestMapping(value = "/deleteFile", method=RequestMethod.POST) public ResponseEntity<String> deleteFile(String fileName){ logger.info("delete file: " + fileName); String formatName = fileName.substring(fileName.lastIndexOf(".")+1); MediaType mType = MediaUtils.getMediaType(formatName); if(mType != null) { String front = fileName.substring(0, 12); String end = fileName.substring(14); new File(uploadPath + (front + end).replace('/', File.separatorChar)).delete(); } new File(uploadPath + fileName.replace('/', File.separatorChar)).delete(); return new ResponseEntity<String>("deleted", HttpStatus.OK); } }

 

10) /sboard/register.jsp --> 추가

<bash />
<!-- 아래 추가 --> <style> .fileDrop { width: 80%; height: 100px; border: 1px dotted gray; background-color: lightslategrey; margin: auto; } small { margin-left: 3px; font-weight: bold; color: gray; } </style> <form id='registerForm' role="form" method="post"> <!-- 아이디 추가 --> <tr> <td>파일첨부</td> <td><label for="exampleInputEmail1">File DROP Here</label> <div class="fileDrop"></div> <ul class="uploadedList"></ul> </td> </tr> <!-- 아래 <스크립트> 모두 추가 --> <script> $(".fileDrop").on("dragenter dragover", function(event) { // 이벤트 처리를 제한한다. // 파일을 영역에 끌어다 놓아도 아무런 변화가 없게 처리 event.preventDefault(); }); $(".fileDrop").on("drop", function(event){ event.preventDefault(); // event.originalEvent : 전달된 파일 데이터를 가져오는 부분 // event.dataTransfer : 이벤트와 같이 전돨된 데이터를 의미하고, // 그 안에 포함된 파일 데이터를 찾아내기 위해서 dataTransfer.files를 이용한다. var files = event.originalEvent.dataTransfer.files; var file = files[0]; //console.log(file); // formData : <form> 태그로 만든 데이터 전송 방식과 동일하게 데이터를 전송할 수 있다. var formData = new FormData(); formData.append("file", file); // 파일 객체를 추가 // 파일 데이터를 전송하기 위해서 processData, contentType 두 옵션을 반드시 false 지정 // 두개의 옵션은 데이터 전송을 <form> 태그를 이용하는 파일 업로드와 동일하게 해주는 역활 //url: 절대경로 슬러시 삭제 $.ajax({ url: 'uploadAjax', data: formData, dataType:'text', processData: false, contentType: false, type: 'POST', success: function(data){ //alert(data); //추가 페이지 var str =""; if(checkImageType(data)){ str ="<div><a href=displayFile?fileName="+getImageLink(data)+">" +"<img src='displayFile?fileName="+data+"'/>" +"</a><small data-src="+data+" style='cursor:pointer' title='삭제'>X</small></div>"; }else{ str = "<div><a href='displayFile?fileName="+data+"'>" + getOriginalName(data)+"</a>" +"<small data-src="+data+" style='cursor:pointer' title='삭제'>X</small></div></div>"; } $(".uploadedList").append(str); } }); }); $(".uploadedList").on("click", "small", function(event){ var that = $(this); //url: 절대경로 슬러시 삭제 $.ajax({ url:"deleteFile", type:"post", data: {fileName:$(this).attr("data-src")}, dataType:"text", success:function(result){ if(result == 'deleted'){ that.parent("div").remove();//화면에서 삭제처리 } } }); }); //삭제 설명 //사용자가 <small>태그로 처리된 'x'를 클릭하면 //'data-src'속성값으로 사용된 파일의 이름을 얻어와서 POST 방식으로 호출처리 //글쓰기 버튼 클릭시 첨부내용 <input>태크 포함 처리 $("#registerForm").submit(function(event){ event.preventDefault(); var that = $(this); var str =""; $(".uploadedList small").each(function(index){ str += "<input type='text' name='files["+index+"]' value='"+$(this).attr("data-src") +"'> "; }); alert(str); that.append(str); that.get(0).submit(); }); </script> <script> // 파일 첨부시 이름만 뽑아오는 코드 function getOriginalName(fileName){ if(checkImageType(fileName)){ return; } var idx = fileName.indexOf("_") + 1 ; return fileName.substr(idx); } function getImageLink(fileName){ if(!checkImageType(fileName)){ return; } var front = fileName.substr(0,12); //년,월,일 경로 추출하는 용도 var end = fileName.substr(14); //파일 이름 앞의 's_'까지의 값 return front + end; //'s_'값을 제외한 결과 값 } //전송 문자열이 이미지 파일인지 확인 여부 function checkImageType(fileName){ var pattern = /jpg|gif|png|jpeg/i; return fileName.match(pattern); } </script>

 

 

11) BoardDAO.java --> 추가

<bash />
public List<String> getAttach(Integer bno) throws Exception; // 첨부파일 list 보기(view 페이지에서)

 

12) BoardDAOImpl.java --> 추가

<bash />
@Override public List<String> getAttach(Integer bno) throws Exception { return session.selectList(namespace+".getAttach", bno); }

 

13) boardMapper.xml --> 추가

<bash />
<select id="getAttach" resultType="string"> select fullName from tbl_attach where bno = #{bno} order by fullName asc </select>

 

14) BoardService.java --> 추가

<bash />
public List<String> getAttach(Integer bno) throws Exception;

 

15) BoardServiceImpl.java --> 추가

<bash />
@Override public List<String> getAttach(Integer bno) throws Exception { return dao.getAttach(bno); }

 

16) SearchBoardController.java --> 추가

<bash />
@ResponseBody @RequestMapping("/getAttach/{bno}") public List<String> getAttach(@PathVariable("bno") Integer bno)throws Exception{ return service.getAttach(bno); }

 

17) /sboard/read.jsp --> 추가

<bash />
<!-- 이미지를 보여주기 위해 화면상 히든 처리 --> <style type="text/css"> .popup { position: absolute;} .back { background-color: gray; opacity:0.5; width: 10%; height: 20%; overflow:hidden; z-index:1101;} .front { z-index:1110; opacity:1; boarder:1px; margin: auto; } .show{ position:relative; max-width: 100%; max-height: 100%; overflow: auto; } </style> <div class='popup back' style="display:none;"></div> <div id="popup_front" class='popup front' style="display:none;"> <img id="popup_img"> </div> <center> ~~ <!-- 첨부파일 출력 부분 추가 --> <table class="uploadedList"></table> <!-- 첨부파일 출력에 관한 스크립트 --> <script> //첨부파일 정보 var bno = ${boardVO.bno}; //객체명 매칭 처리 $.getJSON("/sboard/getAttach/"+bno,function(list){ $(list).each(function(){ var fileInfo = getFileInfo(this); var str_content = ""; if(checkImageType(this)){ str_content = "<tr><td class='info'><a href="+fileInfo.getLink+">" +"<img src=/upload/"+fileInfo.fullName+"></td></tr>"; }else{ str_content = "<tr><td><a href="+fileInfo.getLink+">"+fileInfo.fullName+"</td></tr>"; } $(".uploadedList").append(str_content); }); }); //파일첨부 히든 영역에 큰 이미지로 보여주기 $(".uploadedList").on("click", ".info a", function(event){ var fileLink = $(this).attr("href"); if(checkImageType(fileLink)){ event.preventDefault(); var imgTag = $("#popup_img"); imgTag.attr("src", fileLink); console.log(imgTag.attr("src")); $(".popup").show('slow'); imgTag.addClass("show"); } }); $("#popup_img").on("click", function(){ $(".popup").hide('slow'); }); //파일 정보 (이미지 판별) function checkImageType(fileName){ var pattern = /jpg|gif|png|jpeg/i; return fileName.match(pattern); } function getFileInfo(fullName){ var fileName,imgsrc, getLink; var fileLink; if(checkImageType(fullName)){ imgsrc = "/displayFile?fileName="+fullName; fileLink = fullName.substr(14); var front = fullName.substr(0,12); // /2021/08/11/ var end = fullName.substr(14); // 's_' getLink = "/displayFile?fileName="+front + end; }else{ imgsrc ="/resources/dist/img/file.png"; fileLink = fullName.substr(12); getLink = "/displayFile?fileName="+fullName; } fileName = fileLink.substr(fileLink.indexOf("_")+1); return {fileName:fileName, imgsrc:imgsrc, getLink:getLink, fullName:fullName}; } </script> <!-- 추가 끝 2 --> <%@ include file="/WEB-INF/views/sboard/test.jsp" %> </center>

 

 

'JAVA > spring' 카테고리의 다른 글

member_fullcode  (0) 2023.05.09
이클립스에 spring 연동시키는 법  (0) 2023.05.08
스프링 댓글 구현  (0) 2023.05.04
스프링 member 구현  (0) 2023.05.03
스프링 Board 구현_넘버링, 검색  (0) 2023.05.03
profile

데일리로그C:

@망밍

포스팅이 도움됐다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!