목차
파일 다운로드를 위한 HTTP 해더 서버에 저장된 파일을 다운 받기 위해서는 Response 해더에 Content-Disposition
정보가 필요합니다.
Content-Disposition 는 HTTP 프로토콜에서 사용되는 헤더로, 서버가 클라이언트에게 제공하는 콘텐츠가 브라우저에 표시될지 또는 다운로드할지, 그리고 다운로드될 경우 파일 이름은 무엇인지 등을 지정합니다.
Content-Disposition 는 inline
, attachment
두 가지 종류가 있습니다. Content-Disposition 값이 inline 면 콘텐츠가 브라우저에서 직접 표시됩니다. attachment 면 콘텐츠가 다운로드를 위한 파일로 제공됩니다. filename 속성을 이용하면 다운로드하기 위한 파일이름을 지정할 수 있습니다.
// Content-Disposition 값이 inline 일 경우 브라우저에 직접 표시됩니다. Content-Disposition : inline// attachment 일 경우 리소스를 파일로 다운로드할 수 있습니다. filename 속성을 통해 파일 이름을 지정할 수 있습니다. Content-Disposition : attachment; filename="example.txt"
리소스 다운로드 서비스 구현 리소스를 반환하는 Response 객체에 Content-Disposition
해더를 추가해줍니다.
String contentDisposition = "attachment; filename=\"" + encodedUploadFileName + "\"" ;
Resource 객체로 업로드된 파일을 전송한다. UrlResource 객체를 이용해 특정 경로에 저장된 Resource 를 가져온 후 ResponseEntity 의 Body에 넣어서 반환한다.
@GetMapping("/attach/{itemId}") public ResponseEntity<Resource> downloadAttach (@PathVariable Long itemId) throws MalformedURLException { Item item = itemRepository.findById(itemId); String storeFileName = item.getAttachFile().getStoreFileName(); String uploadFileName = item.getAttachFile().getUploadFileName(); UrlResource resource = new UrlResource ("file:" + fileStore.getFullPath(storeFileName)); log.info("uploadFileName={}" , uploadFileName); String encodedUploadFileName = UriUtils.encode(uploadFileName, StandardCharsets.UTF_8); String contentDisposition = "attachment; filename=\"" + encodedUploadFileName + "\"" ; return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition) .body(resource); }
전체 코드 @Slf4j @Controller @RequiredArgsConstructor public class ItemController { private final ItemRepository itemRepository; private final FileStore fileStore; @GetMapping("/items/new") public String newItem (@ModelAttribute ItemForm form) { return "item-form" ; } @PostMapping("/items/new") public String saveItem (@ModelAttribute ItemForm form, RedirectAttributes redirectAttributes) throws IOException { UploadFile attachFile = fileStore.storeFile(form.getAttachFile()); List<UploadFile> storeImageFiles = fileStore.storeFiles(form.getImageFiles()); Item item = new Item (); item.setItemName(form.getItemName()); item.setAttachFile(attachFile); item.setImageFiles(storeImageFiles); itemRepository.save(item); redirectAttributes.addAttribute("itemId" , item.getId()); return "redirect:/items/{itemId}" ; } @GetMapping("/items/{id}") public String items (@PathVariable Long id, Model model) { Item item = itemRepository.findById(id); model.addAttribute("item" , item); return "item-view" ; } @ResponseBody @GetMapping("/images/{filename}") public Resource downloadImage (@PathVariable String filename) throws MalformedURLException { return new UrlResource ("file:" + fileStore.getFullPath(filename)); } @GetMapping("/attach/{itemId}") public ResponseEntity<Resource> downloadAttach (@PathVariable Long itemId) throws MalformedURLException { Item item = itemRepository.findById(itemId); String storeFileName = item.getAttachFile().getStoreFileName(); String uploadFileName = item.getAttachFile().getUploadFileName(); UrlResource resource = new UrlResource ("file:" + fileStore.getFullPath(storeFileName)); log.info("uploadFileName={}" , uploadFileName); String encodedUploadFileName = UriUtils.encode(uploadFileName, StandardCharsets.UTF_8); String contentDisposition = "attachment; filename=\"" + encodedUploadFileName + "\"" ; return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, contentDisposition) .body(resource); } }