๐
๋ ์ง
2025-04-28
๐ ํ์ต ๋ด์ฉ
1๏ธโฃ ํ์ผ ๋ค์ด๋ก๋ ์ปจํธ๋กค๋ฌ ๊ตฌํ
@GetMapping(value="/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@ResponseBody
public ResponseEntity<Resource> download(@RequestParam("path") String path) throws UnsupportedEncodingException {
log.info("GET /file/download..." + path);
Resource resource = new FileSystemResource(path);
if (!resource.exists()) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
String filename = resource.getFilename();
HttpHeaders headers = new HttpHeaders();
headers.add(
"Content-Disposition",
"attachment; filename=" + new String(filename.getBytes("UTF-8"), "ISO-8859-1")
);
return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}
2๏ธโฃ ํ์ผ ๋ค์ด๋ก๋ ์ฒ๋ฆฌ ํต์ฌ ํฌ์ธํธ
ํญ๋ชฉ | ์ค๋ช
|
---|
@GetMapping("/download") | ํ์ผ ๋ค์ด๋ก๋ ์์ฒญ์ ์ฒ๋ฆฌํ๋ ์๋ํฌ์ธํธ |
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE | ๋ธ๋ผ์ฐ์ ๊ฐ ํ์ผ๋ก ์ธ์ํด์ ๋ค์ด๋ก๋ํ๊ฒ ํจ |
Resource resource = new FileSystemResource(path) | ์์ฒญ๋ฐ์ ๊ฒฝ๋ก์ ํ์ผ์ Resource ๊ฐ์ฒด๋ก ์์ฑ |
resource.exists() | ํ์ผ์ด ์กด์ฌํ์ง ์์ผ๋ฉด 404 Not Found ๋ฐํ |
Content-Disposition ํค๋ ์ค์ | ํ์ผ ๋ค์ด๋ก๋ ๋ฐฉ์์ผ๋ก ๋ณํ (attachment) |
ํ์ผ๋ช
์ธ์ฝ๋ฉ | UTF-8 โ ISO-8859-1 ๋ณํ (ํ๊ธ, ํน์๋ฌธ์ ๊นจ์ง ๋ฐฉ์ง) |
ResponseEntity<Resource> ๋ฐํ | ๋ณธ๋ฌธ + ํค๋ + HTTP ์ํ์ฝ๋๋ฅผ ํจ๊ป ์ ๋ฌ |
3๏ธโฃ ํ์ผ ๋ฆฌ์คํธ ์ถ๋ ฅ JSP ํ๋ฆ
<h1>/file/list</h1>
<div>${uploadPath}</div>
<!-- ์
๋ก๋ ํด๋ ๊ตฌ์กฐ ์ํ -->
<c:forEach items='${uploadPath.listFiles()}' var='subdir'>
<hr>
FOLDER : ${subdir.getPath()}
<c:forEach items='${subdir.listFiles()}' var='file'>
<br />
- FILE :
<a href="javascript:void(0)" class="item"
data-dir="${subdir.getPath()}" data-filename="${file.getName()}">
${file.getPath()}
</a>
</c:forEach>
<hr>
</c:forEach>
<script>
const projectPath = '${pageContext.request.contextPath}';
const item_els = document.querySelectorAll('.item');
item_els.forEach((item)=>{
item.addEventListener('click', function(){
const filepath = encodeURIComponent(item.getAttribute('data-dir') + "\\" + item.getAttribute('data-filename'));
location.href = projectPath + "/file/download?path=" + filepath;
})
})
</script>
4๏ธโฃ ํ์ผ ๋ฆฌ์คํธ ์ถ๋ ฅ ํ๋ฆ ํต์ฌ ํฌ์ธํธ
ํญ๋ชฉ | ์ค๋ช
|
---|
uploadPath.listFiles() | ์ต์์ ์
๋ก๋ ๋๋ ํ ๋ฆฌ์ ์๋ธ ํด๋๋ค์ ์ํ |
subdir.listFiles() | ๊ฐ ์๋ธ ํด๋ ๋ด๋ถ ํ์ผ ๋ฆฌ์คํธ ์ถ๋ ฅ |
<a> ๋งํฌ ํด๋ฆญ ์ | ํ์ผ ๋ค์ด๋ก๋ ์์ฒญ ๋ฐ์ |
encodeURIComponent | ํ์ผ ๊ฒฝ๋ก๋ฅผ URL-safe ํ์์ผ๋ก ์ธ์ฝ๋ฉํ์ฌ ์๋ฒ๋ก ์ ์ก |
์ค๋ฌด ์ฃผ์์ฌํญ | ์๋ฒ์ ํ์ผ ์์คํ
๊ฒฝ๋ก๋ฅผ ์ง์ ์ฌ์ฉ์์๊ฒ ์ ๊ณตํ๋ฉด ์ ๋จ |
๐ฅ ์ต์ข
์ ๋ฆฌ
- ๋ค์ด๋ก๋ ๊ธฐ๋ฅ์
Resource
๊ฐ์ฒด๋ฅผ ํตํด ํ์ผ์ ์ฝ๊ณ , ์ ์ ํ ํค๋๋ฅผ ์ถ๊ฐํ์ฌ ํด๋ผ์ด์ธํธ๋ก ๋ฐํํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋ค.
- ํ์ผ๋ช
์ ํ๊ธ์ด๋ ํน์๋ฌธ์๊ฐ ํฌํจ๋์ด ์์ ๊ฒฝ์ฐ ๋ฐ๋์ UTF-8 โ ISO-8859-1 ์ธ์ฝ๋ฉ์ ์ ์ฉํ์ฌ ๊นจ์ง์ ๋ฐฉ์งํด์ผ ํ๋ค.
- ํ์ผ์ด ์กด์ฌํ์ง ์์ ๊ฒฝ์ฐ 404 ์๋ฌ๋ฅผ ๋ฐํํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ๋ค.
- ํ์ผ ๋ฆฌ์คํธ ์ถ๋ ฅ์ JSP์์ ์
๋ก๋๋ ํด๋์ ํ์ผ๋ค์ ์ํํ์ฌ ์ถ๋ ฅํ๊ณ , ํ์ผ๋ณ ๋ค์ด๋ก๋ ๋งํฌ๋ฅผ ์ ๊ณตํ๋ค.
- ๋ค์ด๋ก๋ ๋งํฌ ์์ฒญ ์ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์์ ํ๊ฒ ์ธ์ฝ๋ฉํ์ฌ ์๋ฒ์ ์ ๋ฌํ๋ค.
- ๋ณด์์, ํ์ผ ์์คํ
๊ฒฝ๋ก๋ฅผ ์ง์ ์ ๊ณตํ๋ ๊ฒ์ ์ํํ๋ฏ๋ก ์ค๋ฌด์์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๋ ๋ฐฉ์์ผ๋ก ๋ณด์ํ ํ์๊ฐ ์๋ค.
๐ ์ฐธ๊ณ ์๋ฃ