[Spring] 파일업로드 (+방명록에 적용)
필요한 파일을 세팅하자
방명록만들기에서 사용한 파일 중 복붙하기
pom.xml (Overview에서 Artifact Id와 프로젝트 Name만 수정)
resources의 5개 패키지(내용 수정 필요 / WebInitializer.java / Context_1_dataSource.java / Context_2_mybatis.java 세 파일은 동일하게 사용)
파일업로드를 위한 라이브러리 다운로드
https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
Apache Commons FileUpload 1.3.1버전 Maven 영역 복사하여
pom.xml의 <dependencies> </dependencies> 영역 사이에 붙여넣기
파일업로드를 위한 라이브러리 다운로드
https://mvnrepository.com/artifact/commons-io/commons-io
Apache Commons IO 2.4버전Maven 영역 복사하여
pom.xml의 <dependencies> </dependencies> 영역 사이에 붙여넣기
PhotoVO.java
package vo;
import org.springframework.web.multipart.MultipartFile;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class PhotoVO {
//우리가 전송하는 데이터? 제목과 파일!
private String title; //우리가 설정한 제목
private String fileName; //실제 파일 이름
private MultipartFile photo; //사진이든 동영상이든 일단 정보를 담아주자
}
Context_4_fileUpload.java
package context;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
@Configuration
public class Context_4_fileUpload {
@Bean
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setDefaultEncoding("UTF-8");
multipartResolver.setMaxUploadSize(10485760);//최대업로드용량 지정 10mb정도
return multipartResolver;
}
}
이와같이 전에 없던 Context파일을 생성한다면 WebInitializer.java의
해당 영역에 추가해줘야함
FileUploadController.java
package com.korea.upload;
import java.io.File;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class FileUploadController {
static final String VIEW_PATH = "WEB-INF/views/";
@RequestMapping(value= {"/","insert_form.do"})
public String insert_form() {
return VIEW_PATH+"insert_form.jsp";
}
}
컨트롤러의 객체는 ServletContext파일에서 만드는데 이번처럼 파일업로드의 경우
db사용이 없으므로 수동탐색하지 않아도됨
자동탐색으로 만들어보자
**참고로 db사용이 없으므로 upload.xml 파일에도 입력되는 쿼리 없음
**자동탐색으로 만드는 경우 자동생성파일인 HomeController와 충돌하여 오류를 발생시킬 수 있으므로 HomeController파일은 삭제한다.
ServletContext.java
package mvc;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
@ComponentScan("com.korea.upload") //자동탐색
//어노테이션에도 상속관계가 있다
/*
*@Component
* ㄴ@Controller
* ㄴ@Service
* ㄴ@Repository
* */
//컴포넌트의 자식객체가 들어있으면 사실 Controller가 아니어도 만들어 질 수 있다.
public class ServletContext implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
// @Bean
// public InternalResourceViewResolver resolver() {
// InternalResourceViewResolver resolver = new InternalResourceViewResolver();
// resolver.setViewClass(JstlView.class); resolver.setPrefix("/WEB-INF/views/");
// resolver.setSuffix(".jsp"); return resolver; }
}
insert_form.jsp
<%@ 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>
<script type="text/javascript">
function send(f){
f.action = "upload.do";
f.submit();
}
</script>
</head>
<body>
<form method="POST" enctype="multipart/form-data">
제목 : <input name = "title"><br>
사진 : <input type = "file" name = "photo"><br>
<input type = "button" value = "전송" onclick="send(this.form)">
</form>
</body>
</html>
FileUploadController.java
@Autowired : 필드주입 어노테이션 (내장객체 지원)
package com.korea.upload;
import java.io.File;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import vo.PhotoVO;
@Controller
public class FileUploadController {
//필드주입 어노테이션
//session, request와 같은 내장객체를 스프링에서도 지원함
@Autowired
HttpServletRequest request;
static final String VIEW_PATH = "WEB-INF/views/";
@RequestMapping(value= {"/","insert_form.do"})
public String insert_form() {
return VIEW_PATH+"insert_form.jsp";
}
@RequestMapping("upload.do")
public String upload(PhotoVO vo) {
//우선 우리가 지정한 경로에 파일이 잘 업로드되는지 확인하자
String webPath ="/resources/upload"; //상대경로
String savePath = request.getServletContext().getRealPath(webPath); //절대경로
/* ServletContext app = request.getServletContext(); //위에서 autowired로 필드주입했기때문에 리퀘스트 사용가능
* app.getRealPath(webPath); //36행처럼 한줄로 줄여버릴 수 있음
*/
//업로드된 파일의 정보
//MultipartRequest 클래스가 없기 때문에 MultipartFile로 받는다
MultipartFile photo = vo.getPhoto();
String filename="no_file";
if(!photo.isEmpty()) { //비어있지 않을 때
//getOriginalFilename() : 업로드된 실제 파일명 반환
//getName() : 파라미터의 이름(input태그의 이름) 반환
filename = photo.getOriginalFilename();
//파일을 저장할 경로 지정
File saveFile = new File(savePath,filename);
//만약 경로가 없다면 폴더를 만들어라
if(!saveFile.exists()) {
saveFile.mkdirs(); //이미지도 폴더로 만들어버림..
}else {
//동일한 이름파일의 경우 폴더형태로 변환 불가하므로 업로드 시간을 붙여서 이름이 중복되는 것을 방지
long time = System.currentTimeMillis();
filename = String.format("%d_%s", time,filename);
saveFile = new File(savePath,filename);
}
//물리적으로 파일을 변환하는 코드
try {
photo.transferTo(saveFile);
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
vo.setFileName(filename); //vo.getPhoto()로 얻어온 파일정보에서 파일이름을 뽑아내 저장
//기존에는 model로 바인딩했는데 request로 바인딩해보자!
request.setAttribute("vo", vo);
return VIEW_PATH+"input_result.jsp";
}
}
input_result.jsp
<%@ 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>
제목 : ${vo.title}<br>
<img src = "${pageContext.request.contextPath}/resources/upload/${vo.fileName}" width="150">
</body>
</html>
실행결과
방명록만들기(이전글)에 사진업로드를 적용해보자!
1. 파일업로드 프로젝트의 pom.xml 파일을 방명록만들기 프로젝트의 pom.xml 파일로 붙여넣기한다.
2.Context_4_fileUpload.java 파일을 방명록만들기 프로젝트에도 추가(붙여넣기)한다. + 방명록만들기 프로젝트 WebInitializer.java 내용도 추가
3. 방명록만들기 프로젝트의 mapper파일인 visit.xml 새글추가 쿼리 부분에 파일이름도 추가(사진참고)
4. 여기까지 했을때, VISIT 테이블 자체에는 filename 속성이 없으므로 추가해줘야함
쿼리문 :
ALTER TABLE VISIT ADD FILENAME VARCHAR2(100);
5. 방명록만들기 프로젝트의 VisitVO.java 파일도 추가하자
사진을 가져와서 filename 추출가능하게끔 하기위해,,
6. visit_insert_form.jsp 바디영역에 해당내용추가
7. VisitController.java 해당내용추가
8. visit_list.jsp 바디영역에 해당내용추가
실행결과