일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 예외미루기
- 객체 비교
- 한국건설관리시스템
- 인터페이스
- abstract
- 사용자예외클래스생성
- 대덕인재개발원
- GRANT VIEW
- cursor문
- 어윈 사용법
- Java
- NestedFor
- 컬렉션프레임워크
- 정수형타입
- oracle
- 환경설정
- 생성자오버로드
- 추상메서드
- EnhancedFor
- 집합_SET
- 오라클
- exception
- 다형성
- 제네릭
- 자동차수리시스템
- 참조형변수
- 자바
- 컬렉션 타입
- 예외처리
- 메소드오버로딩
- Today
- Total
거니의 velog
(7) 스프링에서 지원하는 여러 가지 기능 1 본문
* 스프링 프레임워크는 오픈 소스이기 때문에 상당히 많은 기능을 지원한다. 이번에는 여러 오픈 소스 라이브러리를 사용해 다중 파일 업로드, 썸네일 이미지, 이메일, 인터셉터 등 여러 가지 기능을 구현해 보자.
1. 다중 파일 업로드하기
* 스프링의 CommonsMultipartResolver 클래스를 이용하면 여러 개의 파일을 한꺼번에 업로드할 수 있다. 다음 표에 CommonsMultipartResolver 클래스의 여러 가지 속성을 정리했다.
< CommonsMultipartResolver 클래스 속성 >
속성 | 설명 |
maxUploadSize | 최대로 업로드가 가능한 파일의 크기를 설정한다. |
maxInMemorySize | 디스크에 임시 파일을 생성하기 전 메모리에 보관할 수 있는 최대 바이트 크기를 설정한다. |
defaultEncoding | 전달되는 매개변수의 인코딩을 설정한다. |
1. 다음과 같이 파일을 준비한다.
2. 파일 업로드에 필요한 라이브러리를 설치하도록 pom.xml을 작성한다.
<!-- 다중 파일 업로드 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>
3. servlet-context.xml 파일에서 CommonsMultipartResolver 클래스를 multipartResolver 빈으로 설정한다.
<!-- 멀티파트 리졸버 -->
<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<beans:property name="maxUploadSize" value="52428800" />
<beans:property name="maxInMemorySize" value="1000000" />
<beans:property name="defaultEncoding" value="utf-8" />
</beans:bean>
4. 파일 업로드 및 다운로드 기능 컨트롤러를 구현하기 위한 자바 파일들을 준비한다.
5. 먼저 파일 다운로드 컨트롤러인 FileDownloadController 클래스를 다음과 같이 작성한다. 버퍼 기능을 이용해 빠르게 브라우저로 이미지 파일을 전송한다.
package com.myspring.pro28.ex01;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class FileDownloadController {
// 파일 저장 위치를 지정한다.
private static String CURR_IMAGE_REPO_PATH = "c:\\spring\\image_repo";
@RequestMapping("/download")
public void download(@RequestParam("imageFileName") String imageFileName, // 다운로드 할 이미지 파일 이름을 전달한다.
HttpServletResponse response) throws Exception {
OutputStream out = response.getOutputStream();
String downFile = CURR_IMAGE_REPO_PATH + "\\" + imageFileName;
File file = new File(downFile); // 다운로드 할 파일 객체를 생성한다.
response.setHeader("Cache-Control", "no-cache");
response.addHeader("Content-disposition", "attachment; fileName=" + imageFileName); // 헤더에 파일 이름을 설정한다.
FileInputStream in = new FileInputStream(file);
byte[] buffer = new byte[1024 * 8];
while (true) {
int count = in.read(buffer); // 버퍼에 읽어들인 문자개수
if (count == -1) // 버퍼의 마지막에 도달했는지 체크
break;
out.write(buffer, 0, count);
} // 버퍼를 이용해 한 번에 8Kbyte씩 브라우저로 전송한다.
in.close();
out.close();
}
}
6. 파일 업로드 컨트롤러를 구현한다. 파일과 매개변수를 같이 전송하므로 Map을 사용한다. 매개변수의 name/value를 다시 map의 key/value로 저장한다. 파일 이름을 ArrayList에 저장한 후 다시 map에 key/value로 저장한다.
package com.myspring.pro28.ex01;
import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class FileUploadController {
private static final String CURR_IMAGE_REPO_PATH = "c:\\spring\\image_repo";
@RequestMapping(value = "/form")
public String form() {
return "uploadForm";
} // 업로드 창인 uploadForm.jsp를 반환한다.
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public ModelAndView upload(MultipartHttpServletRequest multipartRequest, HttpServletResponse response)
throws Exception {
multipartRequest.setCharacterEncoding("utf-8");
Map map = new HashMap(); // 매개변수 정보와 파일 정보를 저장할 Map을 생성한다.
Enumeration enu = multipartRequest.getParameterNames();
while (enu.hasMoreElements()) {
String name = (String) enu.nextElement();
String value = multipartRequest.getParameter(name);
// System.out.println(name+", "+value);
map.put(name, value);
} // 전송된 매개변수 값을 key/value로 map에 저장한다.
List fileList = fileProcess(multipartRequest);
map.put("fileList", fileList); // 파일을 업로드한 후 반환된 파일 이름이 저장된 fileList를 다시 map에 저장한다.
ModelAndView mav = new ModelAndView();
mav.addObject("map", map);
mav.setViewName("result"); // map을 결과창으로 포워딩한다.
return mav;
}
private List<String> fileProcess(MultipartHttpServletRequest multipartRequest) throws Exception {
List<String> fileList = new ArrayList<String>();
Iterator<String> fileNames = multipartRequest.getFileNames(); // 첨부된 파일 이름을 가져온다.
while (fileNames.hasNext()) {
String fileName = fileNames.next();
MultipartFile mFile = multipartRequest.getFile(fileName); // 파일 이름에 대한 MultipartFile 객체를 가져온다.
String originalFileName = mFile.getOriginalFilename(); // 실제 파일 이름을 가져온다.
fileList.add(originalFileName); // 파일 이름을 하나씩 fileList에 저장한다.
File file = new File(CURR_IMAGE_REPO_PATH + "\\" + fileName);
if (mFile.getSize() != 0) { // File Null Check ==> 첨부된 파일이 있는지 체크한다.
if (!file.exists()) { // 경로상에 파일이 존재하지 않을 경우
if (file.getParentFile().mkdirs()) { // 경로에 해당하는 디렉토리들을 생성
file.createNewFile(); // 이후 파일 생성
}
}
mFile.transferTo(new File(CURR_IMAGE_REPO_PATH + "\\" + originalFileName)); // 임시로 저장된 multipartFile을 실제 파일로 전송한다.
}
}
return fileList; // 첨부한 파일 이름이 저장된 fileList를 반환한다.
}
}
7. 파일 업로드창과 업로드한 파일을 표시해 주는 결과창을 나타낼 JSP 파일을 다음과 같이 준비한다.
8. 파일 업로드창인 uploadForm.jsp를 다음과 같이 작성한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<%
request.setCharacterEncoding("UTF-8");
%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<title>파일업로드 하기</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
var cnt = 1; // 파일 업로드 name 값을 다르게 하는 변수이다.
function fn_addFile() {
$("#d_file").append("<br>" + "<input type='file' name='file" + cnt + "' />");
cnt++;
} // 파일 추가를 클릭하면 동적으로 파일 업로드를 추가한다. name 속성의 값으로 'file'+cnt를 설정함으로써 값을 다르게 해준다.
</script>
</head>
<body>
<h1>파일 업로드 하기</h1>
<form method="post" action="${contextPath}/upload" enctype="multipart/form-data"> <!-- 파일 업로드 시 enctype은 반드시 multipart/form-data로 설정해야 한다. -->
<label>아이디:</label>
<input type="text" name="id"><br> <!-- 텍스트 박스에 ID를 입력받아 전송한다. -->
<label>이름:</label>
<input type="text" name="name"><br> <!-- 텍스트 박스에 이름을 입력받아 전송한다. -->
<input type="button" value="파일추가" onclick="fn_addFile()" /><br> <!-- 파일 추가를 클릭하면 동적으로 파일 업로드를 추가한다. -->
<div id="d_file">
</div> <!-- 자바스크립트를 이용해 div 태그 안에 파일 업로드를 추가한다. -->
<input type="submit" value="업로드" />
</form>
</body>
</html>
9. 결과창을 나타내는 result.jsp를 다음과 같이 작성한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>결과창</title>
</head>
<body>
<h1>업로드가 완료되었습니다.</h1>
<label>아이디:</label>
<input type="text" name="id" value="${map.id }" readonly><br> <!-- map으로 넘어온 매개변수 값을 표시한다. -->
<label>이름:</label>
<input type="text" name="name" value="${map.name }" readonly><br> <!-- map으로 넘어온 매개변수 값을 표시한다. -->
<div class="result-images">
<c:forEach var="imageFileName" items="${ map.fileList}">
<%-- <img src="${pageContext.request.contextPath }/download?imageFileName=${imageFileName }" style="width:150px"> --%>
<img src="${pageContext.request.contextPath }/download?imageFileName=${imageFileName }">
<br><br><br>
</c:forEach> <%-- 업로드한 파일을 forEach 문을 이용해 img 태그에 표시한다. --%>
</div>
<p>
<a href='${pageContext.request.contextPath }/form'> 다시 업로드 하기 </a>
</p>
</body>
</html>
10. 다음 주소로 요청하여 ID와 이름을 입력하고 파일추가를 클릭하여 아무 이미지나 세 개의 파일을 첨부한다. 그리고 업로드를 클릭한다.
- http://localhost/pro28/form
11. 결과창으로 넘어가면서 전송된 매개변수 값들과 업로드된 이미지 세 개가 표시된다.
12. 지정한 경로의 폴더를 보면 업로드된 파일들을 볼 수 있다.
2. 썸네일 이미지 사용하기
* 웹 애플리케이션에서 이미지를 표시할 때는 다음과 같이 썸네일(thumbnail) 이미지를 사용하는 경우가 많다.
* 만약 브라우저가 원본 이미지를 모두 전달받는 경우라면 어떨까? 표시할 이미지 개수가 많을 경우에는 시간이 꽤 오래 걸릴 것이다. 이처럼 상품 목록에 이미지를 축소해서 표시하는 경우에는 썸네일 기능을 사용하면 신속하게 표시할 수 있다.
1. 다음과 같이 pom.xml에 썸네일 라이브러리를 설정하면 thumbnailator-0.4.8.jar 가 설치된다.
<!-- 썸네일 이미지 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
2. 컨트롤러에 요청해 썸네일 이미지를 생성한 후 다운로드해 보자. 다음 위치에 FileDownloadController 클래스 파일을 준비한다.
3. 원본 이미지에 대해 썸네일 이미지 파일을 생성한 후 다운로드할 수 있도록 다음과 같이 작성한다.
Thumbnails.of(image).size(50, 50).outputFormat("png").toFile(thumbnail) 은 가로세로 크기가 50 픽셀인 png 썸네일 이미지를 생성한 후 파일로 저장하는 구문이다.
package com.myspring.pro28.ex02;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import net.coobird.thumbnailator.Thumbnails;
@Controller
public class FileDownloadController {
private static String CURR_IMAGE_REPO_PATH = "c:\\spring\\image_repo";
@RequestMapping("/download")
protected void download(@RequestParam("imageFileName") String imageFileName, HttpServletResponse response)
throws Exception {
OutputStream out = response.getOutputStream();
String filePath = CURR_IMAGE_REPO_PATH + "\\" + imageFileName;
File image = new File(filePath);
int lastIndex = imageFileName.lastIndexOf(".");
String fileName = imageFileName.substring(0, lastIndex); // 확장자를 제외한 원본 이미지 파일의 이름을 가져온다.
File thumbnail = new File(CURR_IMAGE_REPO_PATH + "\\" + "thumbnail" + "\\" + fileName + ".png"); // 원본 이미지 파일 이름과 같은 이름의 썸네일 파일에 대한 File 객체를 생성한다.
if (image.exists()) {
thumbnail.getParentFile().mkdirs();
Thumbnails.of(image).size(50, 50).outputFormat("png").toFile(thumbnail);
} // 원본 이미지 파일을 가로세로가 50픽셀인 png 형식의 썸네일 이미지 파일로 생성한다.
FileInputStream in = new FileInputStream(thumbnail);
byte[] buffer = new byte[1024 * 8];
while (true) {
int count = in.read(buffer); // 버퍼에 읽어들인 문자개수
if (count == -1) // 버퍼의 마지막에 도달했는지 체크
break;
out.write(buffer, 0, count);
} // 생성된 썸네일 파일을 브라우저로 전송한다.
in.close();
out.close();
}
}
4. 다음은 실행 결과이다. /form으로 요청한 후 세 개의 이미지 파일을 첨부하고 업로드를 클릭한다.
- http://localhost/pro28/form
5. 결과창에 각 이미지에 대한 썸네일 이미지가 표시된다.
6. 이미지 저장 폴더 하위에 있는 thumbnail 폴더를 보면 다음과 같이 썸네일 이미지들이 있다.
(1) 썸네일 이미지 바로 출력하기
* 쇼핑몰의 상품 목록 이미지 같은 경우 썸네일 이미지 파일을 따로 생성할 필요 없이 썸네일 이미지를 바로 다운로드 하면 훨씬 빨리 표시할 수 있다.
1. 원본 이미지를 썸네일 이미지로 바로 출력하는 방법은 다음과 같다.
@RequestMapping("/download")
protected void download(@RequestParam("imageFileName") String imageFileName, HttpServletResponse response)
throws Exception {
OutputStream out = response.getOutputStream();
String filePath = CURR_IMAGE_REPO_PATH + "\\" + imageFileName;
File image = new File(filePath);
int lastIndex = imageFileName.lastIndexOf(".");
String fileName = imageFileName.substring(0, lastIndex);
File thumbnail = new File(CURR_IMAGE_REPO_PATH + "\\" + "thumbnail" + "\\" + fileName + ".png");
if (image.exists()) {
Thumbnails.of(image).size(50, 50).outputFormat("png").toOutputStream(out); // 원본 이미지에 대한 썸네일 이미지를 생성한 후 OutputStream 객체에 할당한다.
} else {
return;
}
byte[] buffer = new byte[1024 * 8];
out.write(buffer); // 썸네일 이미지를 OutputStream 객체를 이용해 브라우저로 전송한다.
out.close();
}
2. 썸네일 이미지 저장 폴더들의 이미지들을 삭제한 후 다시 실행해 보자.
- http://localhost/pro28/form
3. 브라우저에 표시되는 결과는 앞에서와 같지만 해당 경로의 폴더를 보면 썸네일 이미지 파일은 따로 생성되지 않았다.
'Java_Spring Framework part2' 카테고리의 다른 글
(9) 스프링에서 지원하는 여러 가지 기능 3 (0) | 2023.11.16 |
---|---|
(8) 스프링에서 지원하는 여러 가지 기능 2 (0) | 2023.11.15 |
(6) 메이븐과 스프링 STS 사용법 6 (0) | 2023.11.15 |
(5) 메이븐과 스프링 STS 사용법 5 (0) | 2023.11.15 |
(4) 메이븐과 스프링 STS 사용법 4 (0) | 2023.11.14 |