※ 파일업로드 처리
· enctype 속성을 "multipart/form-data" 로 설정 / method = "post"
· <input type = "file" > 태그 사용
<form name=“frm” method=“post” enctype=“multipart/form-data”>
<input type=“file” name=“filename”>
</form>
· 스프링은 Multipart 지원 기능을 제공하고 있기 때문에, 이 기능을 이용하면
추가적인 처리없이 Multipart 형식으로 전송된 파라미터와 파일 정보를 쉽게 구할 수 있다
- 이 기능을 이용하려면 MultipartResolver 를 스프링 설정 파일에 등록해 주어야 함
▶ MultipartResolver
: Multipart 형식으로 데이터가 전송된 경우, 해당 데이터를 스프링 MVC에서 사용할 수 있도록 변환해줌
MultipartResolver 를 사용하기 위해선 설정파일에 등록해줘야 함
▽ MvcConfiguration.java
@Bean
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver
= new CommonsMultipartResolver();
multipartResolver.setDefaultEncoding("UTF-8"); // 파일 인코딩 설정
multipartResolver.setMaxUploadSizePerFile(5 * 1024 * 1024); // 파일당 업로드 크기 제한 (5MB)
return multipartResolver;
}
- 스프링이 기본으로 제공하는 MultipartResolver는 CommonsMultipartResolver 이다
- CommonsMultipartResolver를 MultipartResolver 로 사용하려면
빈 이름으로 "multipartResolver"를 사용해서 등록하면 됨
- setMaxUploadSizePerFile : 메모리에 보관할 수 있는 최대 바이트크기. 기본 10240 바이트
- setDefaultEncoding : 요청을 파싱할 때 사용할 캐릭터인코딩
▶ 파일 받아오는 3가지방법 (업로드 파일 접근)
[1] @RequestParam 어노테이션이 적용된 MultipartFile 타입의 파라미터를 사용하는 것
- 파일 업로드
form action="submitReport1.do" method="post" enctype="multipart/form-data">
학번: <input type="text" name="studentNumber" />
<br/>
리포트파일: <input type="file" name="report" />
<br/>
<input type="submit" />
</form>
= > 파일은 report 파라미터를 통해서 전달됨 , 이 경우 아래와 같이
@RequestParam 어노테이션과 MultipartFile 타입의 파라미터를 이용해서 업로드 파일 데이터를 전달받을 수 있다
@Controller
public class ReportSubmissionController {
@RequestMapping(value = "/report/submitReport1.do", method = RequestMethod.POST)
public String submitReport1(
@RequestParam("studentNumber") String studentNumber,
@RequestParam("report") MultipartFile report) { **
//MultipartFile이 제공하는 메서드를 이용해서 업로드 데이터 접근
printInfo(studentNumber, report);
return "report/submissionComplete";
}
= > MultipartFile 인터페이스를 이용해서
파일의 이름, 실제 데이터, 파일 크기 등을 구할 수 있다.
[2] 커맨더(commander) 객체를 이용해서 접근한다 (model attribute)
- 커맨드 클래스에 파라미터와 동일한 이름의 MultipartFile 타입 프로퍼티를 추가해주면 됨
import org.springframework.web.multipart.MultipartFile;
public class ReportCommand {
private String studentNumber;
private MultipartFile report;
public String getStudentNumber() {
return studentNumber;
}
public void setStudentNumber(String studentNumber) {
this.studentNumber = studentNumber;
}
public MultipartFile getReport() {
return report;
}
public void setReport(MultipartFile report) {
this.report = report;
}
}
@Controller
public class ReportSubmissionController {
@RequestMapping(value = "/report/submitReport3.do", method = RequestMethod.POST)
public String submitReport3(@ModelAttribute ReportCommand reportCommand) {
printInfo(reportCommand.getStudentNumber(), reportCommand.getReport());
return "report/submissionComplete";
}
[3] MultipartHttpServletRequest를 이용한 업로드 파일 접근
- MultipartHttpServletRequest 인터페이스 = 스프링이 제공하는 인터페이스
▷ MultipartFile getFile(String name) - 파라미터이름이 name 인 업로드 파일정보를 구한다 (하나업로드)
@Controller
public class ReportSubmissionController {
@RequestMapping(value = "/report/submitReport2.do", method = RequestMethod.POST)
public String submitReport2(MultipartHttpServletRequest request) {
String studentNumber = request.getParameter("studentNumber");
MultipartFile report = request.getFile("report"); //요깅
printInfo(studentNumber, report);
return "report/submissionComplete";
}
- FileUploadUtil.java
MultipartHttpServletRequest 인터페이스는 실제로는 어떤 메서드도 선언하고 있지 않으며,
HttpServletRequest 인터페이스와 MultipartRequest 인터페이스를 상속받고 있다
따라서 이런식으로 다운캐스팅 가능
public List<Map<String, Object>> fileUpload(HttpServletRequest request, int uploadFlag)
throws IllegalStateException, IOException {
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request;
▷ MultipartHttpServletRequest 인터페이스의 주요메서드
(다중파일업로드 방법)
· Map<string, multipartfile=""> getFileMap()
- key = 파라미터 이름 , value = 파라미터에 해당하는 파일정보
의 Map을 구한다
- for 문 못돌림. iterator 를 써야함</string,>
- input type file 을 여러개 사용한다
· List<MultipartFile> getFiles(String)
- 파라미터 이름이 name 인 업로드 파일 정보 목록을 구한다
- input에 multiple ="multiple" 넣기
- for 문 돌리기
▽ FileUploadUtil.java
@Component
public class FileUploadUtil {
private static final Logger logger
=LoggerFactory.getLogger(FileUploadUtil.class);
public List<Map<String, Object>> fileUpload(HttpServletRequest request,
int uploadFlag)
throws IllegalStateException, IOException {
MultipartHttpServletRequest multiRequest
= (MultipartHttpServletRequest)request;
Map<String, MultipartFile> fileMap=multiRequest.getFileMap();
//업로드 파일 정보 저장할 List 선언
List<Map<String, Object>> list = new ArrayList<>();
Iterator<String> keyIter=fileMap.keySet().iterator();
while(keyIter.hasNext()) {
String key=keyIter.next();
MultipartFile tempFile = fileMap.get(key); **
//=> 업로드된 파일을 임시파일 형태로 제공
if(!tempFile.isEmpty()) {
long fileSize=tempFile.getSize(); //파일 크기
String oName = tempFile.getOriginalFilename(); //원래 파일명
//변경된 파일이름 구하기
String fileName = getUniqueFileName(oName);
//파일 업로드 처리
//업로드할 폴더 구하기
String uploadPath
= getUploadPath(request, uploadFlag);
File file = new File(uploadPath, fileName);
tempFile.transferTo(file);
//업로드된 파일 정보 저장
//[1] Map에 저장
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("fileName", fileName);
resultMap.put("fileSize", fileSize);
resultMap.put("originalFileName", oName);
//[2] 여러 개의 Map을 List에 저장
list.add(resultMap);
}//if
}//while
return list;
}
▲ MultipartFile 인터페이스
- MultipartFile 인터페이스는 업로드 한 파일 정보 및 파일 데이터를 표현하기 위한 용도로 사용됨
▷MultipartFile 인터페이스의 주요 메서드
· MultipartFile.transferTo()
- 업로드한 파일 데이터를 특정 파일로 저장하고 싶다면 MultipartFile.transferTo() 메서드를 사용하는 것이 편리함
- 업로드한 파일 데이터를 지정한 파일에 저장한다
· getName()
- 파라미터 이름을 구한다
· getOriginalFilename()
- 업로드한 파일의 이름을 구한다
· getSize()
- 업로드한 파일의 크기를 구한다
▶ 같은 파일명이 없도록 [파일명 + 년월일시분초밀리초] 로 파일명 지정하기
- FileUploadUtil.java
public String getUniqueFileName(String fileName) {
//파일명이 중복될 경우 파일이름 변경하기
//파일명에 현재시간(년월일시분초밀리초)을 붙여서 변경된 파일이름 구하기
//a.txt => a_20220602113820123.txt
//순수 파일명만 구하기 => a
int idx = fileName.lastIndexOf(".");
String fileNm = fileName.substring(0,idx); //a
//확장자 구하기
String ext = fileName.substring(idx); // .txt
//변경된 파일이름
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
String today = sdf.format(d);
String result = fileNm + "_" + today + ext;
logger.info("변경된 파일명 : {}", result);
return result;
}
※ 파일 다운로드 처리
▶ 뷰를 결정하는 방법 2가지
[1] 우선순위를 0을 줌으로서 BeanNameViewResolver에서 먼저 찾고
없으면 InternalResourceViewResolver에서 찾게 됨
<beans:bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<beans:property name="order" value="0" />
</beans:bean>
= > beanName이 String 타입으로 return 되었을때 이 BeanNameViewResolver가 받게 됨
BeansNameViewResolver 우선 빈이름으로 결정하고, 빈이름과같은게 없다면
[2] 앞뒤로 prefix suffix를 붙여서 결정한다
@RequiredArgsConstructor 생성자주입
final 붙은 애의 생성자를 만들어줌
dao 에 붙이는거 @Repository
@Service
controller에 붙이는거 @controller
@Component - 객체생성해줘 ~ dao도 service도 controller 도 아닐때 이거 씀
정리
- <input type=file/>로 파일을 받을 수 있다. 이때 form에는 enctype="multipart/form-data" 속성이 있어야 한다.
- multiple="multiple"가 있으면 파일 여러개를 한번에 업로드 할 수 있다.
- 스프링에선 @RequestParam또는 @ModelAttribute으로 MultipartFile file을 받을 수 있다.
- multiple="multiple"이면 List<MultipartFile file>로 받으면 된다.
- file.transferTo(new File("PATH") 을 이용해 파일을 저장할 수 있다.
- 이때 사용자가 업로드한 파일명과 서버 내부에서 저장하는 파일명은 서로 다르게 저장한다. (그니깐 이 두개를 연결해주는 DB테이블이 필요하다.)
- 사용자가 업로드한 파일명은 file.getOriginalFilename() 으로 받을 수 있다.
- 서버 내부에서 저장하는 파일명은 절대 겹치게 설정해선 안된다.(UUID 등을 사용하자.)
- 이미지를 HTML에 보여줄 땐 별도의 컨트롤러가 필요하다.
- new UrlResource("file:" + file.getFullPath(filename));을 이용해 Resource를 리턴하자.
- html에선 <img src=~~>로 컨트롤러에서 넘어오는 Resource를 보여줄 수 있다.
- 파일 다운 링크를 만들기 위해서도 별도의 컨트롤러가 필요하다.
- Response Header에 contentDisposition를 넣어줘야 한다.
- body값으론 Resource를 넣어주면 된다.
'Spring' 카테고리의 다른 글
| [Spring] 게시판 예제 / 이벤트 상품별로 분류하기 / 선택한 체크박스만삭제하기 (0) | 2022.06.14 |
|---|---|
| [Spring] 스프링 작업 순서 / 나를 위한 기초 다지기 (0) | 2022.06.10 |
| [Spring] spring boot 스프링부트 (0) | 2022.05.31 |
| [Spring] mybatis (0) | 2022.05.30 |
| [Spring] 스프링 MVC를 이용한 웹 요청 처리 (0) | 2022.05.26 |