์ด๋ฒ์ ์งํํ๊ณ ์๋ ํ๋ก์ ํธ์์ ํ์ผ์ ์ ๋ก๋ํ๋ ๊ธฐ๋ฅ์ด ํ์ํด์ ๊ณต๋ถํ๊ฒ ๋์๋ค.
1. ๋ ๊ฐ์ง ์ ์ก ๋ฐฉ์
HTML Form์ ๋ฐ์ดํฐ ์ ์ก ๋ฐฉ์์ ํฌ๊ฒ
1. x-www-form-urlencoded
Http Body์ bookname=jpabook&quantity=31 ์ ๊ฐ์ด key-valueํ์์ &๋ก ์ฐ๊ฒฐ์ง์ด ๋ฌธ์๋ฅผ ์ ์กํ๋ค.
2. multipart/form-data
๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ์ ๋ฌธ์ ๋ฐ์ดํฐ๋ฅผ ๋์์ ์ ์กํ ์ ์๋ ๋ฐฉ๋ฒ์ด๋ค.
multipart/form-data์ ๋ํด์ ๋ ์์๋ณด์.
2. multipart/form-data
<form action="/save" method="post" enctype="multipart/form-data">
<input type="text" name="bookname"/>
<input type="file" name="imgfile1" />
</form>
ํผ ๋ฐ์ดํฐ๊ฐ ์๋ฒ๋ก submit ๋ ๋ ์ธ์ฝ๋ฉ ๋๋ ๋ฐฉ์์ ์ง์ ํ๋ enctype(encryptiontype)์ ํด๋น ๋ฐฉ์์ผ๋ก ์ค์ ํ๋ค.
๊ทธ๋ ๊ฒ ์๋์ ๊ฐ์ ํ์์ผ๋ก Http ๋ฉ์์ง๊ฐ ๋ณด๋ด์ง๋ค.
POST /save HTTP/1.1
Host: ~
Content-Type: multipart/form-data; boundary=(random๊ฐ x)
x
Content-Disposition: form-data; name="bookname"
jpa
x
Content-Disposition: form-data; name="imgfile1"; filename="jpa.png"
Content-Type: image/png
4121312asdasd12345f12dfas123...............(binary ๋ฐ์ดํฐ๊ฐ ๋์ด๊ฐ)
x
3-1. ์คํ๋ง์์ multipart ์์ฒญ์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ 1
Form์์ text input๊ณผ file input 2๊ฐ์ง ๋ฐ์ดํฐ๋ฅผ ๋์์ ์ ์กํด๋ณด์๋ค.
HttpServletRequest์๋ ์ด๋ฆ์์๋ถํฐ ์ ์ ์๋ฏ์ด ๋ณต์กํ multipart ์ฒ๋ฆฌ๋ฅผ ์ํ StandardMultipartHttpServletRequest๊ฐ ํ ๋น๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
spring.servlet.multipart.enabled=true
์์ ์ต์ ์ด spring์ ๊ธฐ๋ณธ ์ค์ ์ธ true์ผ ๋๋ง
Spring Boot์ DispatcherServlet์์ MultipartResolver๋ฅผ ์คํํ๋ค.
๊ทธ๋ฆฌ๊ณ http multipart ์์ฒญ์ด ๋ค์ด์ค๋ฉด MultipartResolver๊ฐ ์๋ธ๋ฆฟ ์ปจํ ์ด๋๊ฐ ์ ๋ฌํ๋ ์ผ๋ฐ์ ์ธ HttpServletRequest๋ฅผ MultipartHttpServletRequest๋ก ๋ณํํด์ ๋ฐํํ๋ค.
์ด๋ ๊ฒ ๋๋ฉด ์ปจํธ๋กค๋ฌ์์๋ HttpServletRequest ๋์ ์ MultipartHttpServletReques๋ฅผ ์ฃผ์ ๋ฐ์ ๋ ๋ง์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋ค.
์ด์ HttpServletRequest์์ Part๋ฅผ ์ป์ด์ค๊ณ Part์ ๊ธฐ๋ฅ์ ์ด์ฉํ์ฌ ํ์ผ ๊ด๋ จ ํธ์ ๊ธฐ๋ฅ, ๋ฐ์ดํฐ ์ฝ๊ธฐ, ํ์ผ ์ ์ฅํ๊ธฐ๋ฅผ ํด๋ณด์!
์ฐ์ ํ์ผ์ ์ ์ฅํ ๊ฒฝ๋ก๋ฅผ ์ค์ ํ๋ค.
#application.properties
file.dir = /Users/khs/Documents/Development/workspace/FileUpload/file/
@PostMapping("/upload")
public String saveFileV1(HttpServletRequest request) throws ServletException, IOException {
Collection<Part> parts = request.getParts();
log.info("parts={}", parts);
for (Part part : parts) {
log.info("===== PART =======");
log.info("name={}", part.getName());
Collection<String> headerNames = part.getHeaderNames();
for (String headerName : headerNames) {
log.info("header {}: {}", headerName, part.getHeader(headerName));
}
//ํธ์ ๊ธฐ๋ฅ ๋ฉ์๋
log.info("submittedFileName={}", part.getSubmittedFileName());
log.info("size={}", part.getSize());
//๋ฐ์ดํฐ Read
InputStream inputStream = part.getInputStream();
String body = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
log.info("body={}", body);
//ํ์ผ์ ์ ์ฅํ๊ธฐ
if (StringUtils.hasText(part.getSubmittedFileName())) {
String fullPath = fileDir + part.getSubmittedFileName();
log.info("ํ์ผ ์ ์ฅ fullPath={}", fullPath);
part.write(fullPath);
}
}
}
์์ ๊ฐ์ด ์ด๋ฏธ์ง ํ์ผ์ด ์ ์ ์ฅ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
3-2. ์คํ๋ง์์ multipart ์์ฒญ์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ 2( ์ถ์ฒ! โญ๏ธโญ๏ธโญ๏ธ)
@PostMapping("/upload")
public String saveFile(@RequestParam("itemName") String itemName,
@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
log.info("request={}", request);
log.info("itemName={}", itemName);
log.info("multipartFile={}", file);
if (!file.isEmpty()) {
String fullPath = fileDir + file.getOriginalFilename();
log.info("ํ์ผ ์ ์ฅ fullPath={}", fullPath);
file.transferTo(new File(fullPath)); //ํ์ผ์ ์ฅ
}
return "upload-form";
}
Spring์์ ์ ๊ณตํด์ฃผ๋ Multipart class๋ฅผ ์ด์ฉํ์ฌ ๊ฐํธํ๊ฒ ์ฒ๋ฆฌ ๊ฐ๋ฅํ๋ค.
'๐ Backend > ๐ Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์ฟ ํค, ์ธ์ , ํ ํฐ, Hybrid ํ ํฐ ์ธ์ฆ ๋ฐฉ์์ ์ฐจ์ด (0) | 2023.09.11 |
---|---|
Spring Cloud #1 (0) | 2023.05.28 |
DispatcherServlet์ doDispatch์์ HandlerMapping ๊ณผ์ ์ ๋ํด์ (0) | 2022.07.31 |
Path Variable VS Query Parameter (0) | 2022.07.29 |
์๋ธ๋ฆฟ(Servlet)์ด ๋ฌด์์ธ์ง ๊ฐ์ด ์์๋ณด์! (0) | 2022.07.18 |