<form action="#" enctype="multipart/form-data" th:action="@{/fileupload}" method="post">
File : <input type="file" name="file">
<input type="submit" value="upload">
</form>
- form 태그의 enctype 속성은 form의 data가 server로 submit 될 때 인코딩되는 방법을 의미
인코딩 방법은 3가지의 방법이 있음
* 인코딩(encoding)이란? 파일에 저장된 정보의 형태나 형식을 데이터 표준화, 보안, 처리 속도 향상, 저장 공간 절약 등을 위해서 다른 형태로 변환하는 처리 혹은 그 처리 방식
- application/x-www-form-urlencoded : 기본값으로 모든 문자들은 서버로 보내기 전에 인코딩됨을 명시 (defalut)
- multipart/form-data : 모든 문자를 인코딩하지 않음을 명시, form 태그에서 파일이나 이미지를 전송할 때 주로 사용
- text/plain : 공백 문자(space)는 "+" 기호로 변환하지만 나머지 문자는 모두 인코딩되지 않음을 명시
- multipart/form-data 사용 이유: 기본 값으로 사용되는 application/x-www-form-urlencoded 방식은 문자열로만 데이터를 보내기 때문에 파일을 보낼 수 없음 하지만 multipart/form-data를 사용하면 바이너리 데이터를 보낼 수 있기 때문에 파일을 전송할 수 있음
@PostMapping("/fileupload")
public String fileUpload(@RequestParam MultipartFile file, RedirectAttributes redirectAttributes) throws IOException {
log.info(file.getOriginalFilename());
File converFile = new File(file.getOriginalFilename());
file.transferTo(converFile);
// file.transferTo(new File(file.getOriginalFilename()));
String filename_url = file.getOriginalFilename();
String message = file.getOriginalFilename()+ " 파일이 저장되었습니다.";
redirectAttributes.addFlashAttribute("message",message);
redirectAttributes.addFlashAttribute("filename_url",filename_url);
return "redirect:/upload";
}
- @RequestParam 을 이용하여 MultipartFile을 받고 transferto를 이용해 파일로 변환하여 지정한 경로에 저장하는 방식으로 구현
- RedirectAttributes 클래스를 이용하여 String 형태로 업로드 메세지 전달 (addFlashAttribute - 데이터가 post 형식으로 전달, 세션을 활용해 필요한 데이터만 일회성으로 값을 넘겨줌)
@GetMapping("/download/{filename}")
public ResponseEntity<Resource> fileDownload(@PathVariable String filename) throws IOException {
// log.info(filename);
Resource resource = resourceLoader.getResource("classpath:" + filename);
log.info(String.valueOf(resource.exists()));
File file = resource.getFile();
Tika tika = new Tika();
String mediaType = tika.detect(file);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachement; filename=\"" + resource.getFilename() +"\"")
.header(HttpHeaders.CONTENT_TYPE, mediaType)
.header(HttpHeaders.CONTENT_LENGTH, file.length()+"")
.body(resource);
}
- ResponseEntity는 사용자의 HttpResquest에 대한 응답 데이터를 포함하는 클래스이므로 응답 header , body를 같이 리턴할 수 있는 타입
- PathVariable을 이용하여 URL 경로에 변수를 넣을 수 있음
- Resource는 classpath 기준으로 리소스를 읽어올 수 있음, getResource 메소드로 경로의 리소스를 불러올 수 있음
- Tika 라이브러리 : PPT, CSV ,PDF 등 다양한 형태의, 파일의 메타 데이터와 텍스트를 감지하고 추출하는 라이브러리
- Content-Disposition에 attachment를 주는 경우로, 이때 filename과 함께 주게 되면 body에 오는 값을 다운로드 받으라는 의미
-----------------------------------------------------------------------------------------------------------------------------------
getFile 메소드는 기존(빌드 전)에 classpath 경로에 있는 파일은 읽어들여 다운로드할 수 있지만 새롭게 업로드 하는 파일은 읽어들이지 못해 다운로드가 안되는 에러가 발생하였음. -> 구글링을 통해 알아보니 getFile의 사용을 지양하는듯
그래서 코드를 변경하게 되었다.
@Value("${spring.servlet.multipart.location}")
private String path
@GetMapping("/download/{filename}")
public ResponseEntity<Resource> fileDownload(@PathVariable String filename) throws IOException {
// Resource resource = resourceLoader.getResource("classpath:"+filename);
// Resource resource = new ClassPathResource(filename);
// File file = resource.getFile(); // 수정 전 코드
Path path1 = Paths.get(path + "/" + filename); // 다운로드 할 파일의 최종 경로
String contentType = Files.probeContentType(path1); // 타입 받아오기
Resource resource = new InputStreamResource(Files.newInputStream(path1)); // path1의
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachement; filename=\"" + filename +"\"")
.header(HttpHeaders.CONTENT_TYPE, contentType)
.body(resource);
}
'Spring' 카테고리의 다른 글
Spring layer architechture 3 layer 정리 (0) | 2021.12.01 |
---|