일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 게시판만들기
- Oracle
- service
- delete
- CRUD
- MVC 게시판
- jdbc
- MVC CRUD
- Controller
- 게시판
- MVC설정
- hikaricp
- 서비스계층
- Oracle 연결
- 게시판 List
- log4jdbc
- MVC
- spring
- update
- 환경설정
- mybatis
- log4j
- Connection pool
- Today
- Total
yahayaha
25. ajax 파일 업로드 본문
pox.xml에 설정 셋팅.
서블릿은 3.0 이상 버전으로 사용.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
그리고 web.xml <servlet> 태그 내에 <multipart-config> 태그를 추가.
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<multipart-config>
<location>C:\\upload\\temp</location>
<max-file-size>20971520</max-file-size> <!-- 1MB * 20 -->
<max-request-size>41943040</max-request-size> <!-- 40MB -->
<file-size-threshold>20971520</file-size-threshold> <!-- 20MB -->
</multipart-config>
</servlet>
<multipart-config>의 설정은 특정 사이즈의 메모리 사용(file-size-threshold), 업로드되는 파일을 저장할 공간(location)과
업로드되는 파일의 최대 크기(max-file-size)와 한번에 올릴 수 있는 최대 크기(max-request-size)를 지정 가능.
web.xml 설정은 WAS(Tomcat) 자체의 설정일 뿐이고 스프링에서 업로드 처리는 MultipartResolver라는 타입의 객체를 빈으로 등록해야 사용이 가능. WEB과 관련된 설정은 servlet-context.xml에서 설정.
<beans:bean id="multipartResolver"
class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</beans:bean>
서버상에서 첨부파일의 처리는 컨트롤러에서 이루어지므로 UploadController를 작성.
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import lombok.extern.log4j.Log4j;
@Controller
@Log4j
public class UploadController {
@GetMapping("/uploadForm")
public void uploadForm() {
log.info("upload form");
}
}
UploadController에는 클래스 선언부에 @RequestMapping이 적용되지 않으므로 views폴더에 uploadForm.jsp 추가.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="uploadFormAction" method="post" enctype="multipart/form-data">
<input type="file" name = "uploadFile" mutiple>
<button>Submit</button>
</form>
</body>
</html>
uploadForm.jsp는 간단하게 form 태그만 생성하고 input type=file을 추가.
실제 전송은 iploadFormAction 경로를 이용해서 처리, 파일 업로드에서 가장 신경 써야하는 부분은 enctype의 속성값을 multipart/form-data으로 지정하는것이 가장 중요. 그리고 지금 까지 작업한걸 톰캣으로 확인.
스프링 MVC에는 MultipartFile 타입을 제공해서 업로드되는 파일 데이터를 쉽게 처리 가능.
<input type="file" name = "uploadFile" mutiple>의 name 속성으로 변수를 지정해서 처리.
uploadController에서 코드를 추가해줘야함.
@PostMapping("/uploadFormAction")
public void uploadFormPost(MultipartFile[] uploadFile, Model model) {
for(MultipartFile multipartFile : uploadFile) {
log.info("----------------");
log.info("Upload File Name : " + multipartFile.getOriginalFilename());
log.info("Upload File Size : " + multipartFile.getSize());
}
}
파일 처리는 스프링에서 제공하는 MultipartFile 타입을 이용 화면에서 첨부파일을 여러 개 선택할 수 있으므로 배열 타입으로 설정한 후 파일을 업로드 진행.
파일 업로드 후 submit 클릭 한 뒤 로그를 찍어보면.
이미지의 이름과 파일의 크기를 출력해줌.
String getName() | String getOriginalfileName() | boolean isEmpty() | long getSize() | byte[] getBytes() | InputStream getInputStream() | transferTo(File file) |
파라미터의 이름 <input> 태그의 이름 | 업로드되는 파일의 이름 | 파일이 존재하지 않는 경우true | 업로드되는 파일의 크기 | byte[]로 파일 데이터 변환 | 파일데이터와 연결된 inputStream을 반환 | 파일을 저장 |
파일 저장
업로드되는 파일을 저장하는 방법은 transferTo()를 이용해서 처리 가능.
@PostMapping("/uploadFormAction")
public void uploadFormPost(MultipartFile[] uploadFile, Model model) {
String uploadFolder = "C:\\upload";
for(MultipartFile multipartFile : uploadFile) {
log.info("----------------");
log.info("Upload File Name : " + multipartFile.getOriginalFilename());
log.info("Upload File Size : " + multipartFile.getSize());
File saveFile = new File(uploadFolder, multipartFile.getOriginalFilename());
try {
multipartFile.transferTo(saveFile);
} catch (Exception e) {
log.info(e.getMessage());
}
}
}
transferTo()의 파라미터로는 java.io.File의 객체를 지정하면 되기 때문에 업로드 되는 원래 파일의 이름으로 C 드라이브 upload 폴더에 저장.
Ajax 파일 업로드
첨부파일을 업로드하는 다른 방식은 Ajax를 이용. 파일 데이터만 전송하는 방식이 있음.
Ajax를 이용하는 첨부파일 처리는 FormData라는 객체르 이용함.
우선 UploadController에 GET 방식으로 첨부파일을 업로드하는 페이지 제작하고, views 폴더에 uploadAjax.jsp 작성.
// UploadController
@GetMapping("/uploadAjax")
public void uploadAjax() {
log.info("upload ajax");
}
//uploadAjax
<div class="uploadDiv">
<input type='file' name='uploadFile' multiple>
</div>
<button id='uploadBtn'>upload</button>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"
integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
crossorigin="anonymous"></script>
<script>
$(document).ready(function(){
$("#uploadBtn").on("click", function(e){
var formData = new FormData();
var inputFile = $("input[name='uploadFile']");
var files = inputFile[0].files;
console.log(files);
});
});
</script>
jQuery를 이용하는 경우에 파일 업로드는 FormData라는 객체를 이용. FormData는 가상의 form 태그와 같다고 생각하면 편함. Ajax를 이용하는 파일 업로드는 FormData를 이용해서 필요한 파라미터를 담아서 전송하는 방식.
먼저 데이터 전송하기 전에 여러 개의 파일을 선택했을 때 jQuery에서 파일 데이터를 처리가 가능한지 확인해야함
.
Ajax를 이용해서 첨부파일을 전송하는 경우 가장 중요한 객체는 FormData 타입의 객체.
각 파일 데이터를 추가하는 것과 이를 Ajax로 전송할 때 약간의 옵션이 붙어야함.
그럼 ajax 관련 코드 추가를 해줘야함.
<script>
$(document).ready(function(){
$("#uploadBtn").on("click", function(e){
var formData = new FormData();
var inputFile = $("input[name='uploadFile']");
var files = inputFile[0].files;
console.log(files);
for(var i = 0; i < files.length; i++){
formData.append("uploadFile", files[i]);
}
$.ajax({
url: '/uploadAjaxAction',
processData: false,
contentType: false,
data: formData,
type: 'POST',
success: function(result){
alert("Upload");
}
}); //$.ajax
});
});
</script>
첨부파일 데이터는 fileData를 formData에 추가한 뒤에 Ajax를 통해서 formData 자체를 전송.
이때 processData와 contentType은 반드시 false로 지정해야만 전송되는걸 주의해야함.
UploadController에서는 기존과 동일하게 MultipartFile 타입을 이용해서 첨부파일 데이터를 처리함.
@PostMapping("/uploadAjaxAction")
public void uploadAjaxPost(MultipartFile[] uploadFile) {
log.info("update ajax post...");
String uploadFolder = "C:\\upload";
for(MultipartFile multipartFile : uploadFile) {
log.info("-------------");
log.info("Upload File Name : " + multipartFile.getOriginalFilename());
log.info("Upload File Name : " + multipartFile.getSize());
String uploadFileName = multipartFile.getOriginalFilename();
//인터넷 익스플로러 파일 경로
uploadFileName = uploadFileName.substring(uploadFileName.lastIndexOf("\\") + 1);
log.info("only file name : " + uploadFileName);
File saveFile = new File(uploadFolder, uploadFileName);
try {
multipartFile.transferTo(saveFile);
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
uploadAjaxPost는 기존의 form 태그를 이용하던 방식과 차이가 없지만, Ajax 방식으로 결과 데이터를 전달하면서 리턴 타입이 달라지도록함.
파라미터에서 Ajax 방식을 이용하기 때문에 Model을 사용할 일이 없으니 사용하지 않음.
인터넷 익스플로러(IE) 경우 전체 파일 경로가 전송되므로 마지막에 \를 기준으로 잘라낸 문자열이 실제 파일이 됨.
일단 브라우저에서 정상적으로 파일이 업로드 되는지 확인.
첨부파일을 서버에 전송하고 저장하는 일은 복잡한건 아니지만 생각해야하는 부분이 많이 있음.
1. 동일한 이름으로 파일이 업로드 되었을 때 기존 파일이 사라지는 문제.
2. 이미지 파일의 경우에는 원본 파일의 용량이 큰 경우 섬네일 이미지를 생성해야 하는 문제.
3. 이미지 파일과 일반 파일을 구분해서 다운로드 혹은 페이지에서 조회하도록 처리하는 문제.
4. 첨부파일 공격에 대비하기 위한 업로드 파일의 확장자 제한.
이런 주의점을 생각하면서 개발을 해야함.
'spring > 프로젝트' 카테고리의 다른 글
27-1. 파일 업로드(썸네일 이미지) (0) | 2024.02.17 |
---|---|
26. ajax 파일 업로드 (파일 확장자, 크기 처리, 년/월/일 폴더 처리, UUID 중복 파일 처리) (0) | 2024.02.15 |
24. 댓글 페이징처리. (0) | 2024.02.12 |
23. 댓글 기능( 이벤트 , view 처리) (2) | 2024.02.11 |
22. ajax 댓글 처리 (0) | 2024.02.09 |