๐ก Issue
- Type์ File๋ก ์ ํ์, ๋ก์ปฌ์์ ํ์ผ์ ์๋ฒ๋ก ์ ์กํ์ฌ ์ ์ฅํ๋ ๋ก์ง์ ๊ตฌํํ๋ ์ค์ด๋ค.
- ํ์ผ์ ์๋ฒ๋ก ์ ์กํ ๋, ์ฃผ๋ก Multipart-File์ ์์ฃผ ์ฌ์ฉํ๋ค.
๐ก Multipart-File์ด๋?
- ํด๋ผ์ด์ธํธ์ ์๋ฒ๊ฐ์ ์ ์ก๋๋ HTTP ์์ฒญ-์๋ต์์ ์ฃผ๋ก ํ์ผ ์ ๋ก๋์ ๊ด๋ จํ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ ๋ ์ฌ์ฉ๋๋ค.
- HTTP๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํ ์คํธ ๊ธฐ๋ฐ (JSON)์ผ๋ก ์์ฒญ-์๋ตํ์ง๋ง, ํ์ผ๊ณผ ๊ฐ์ ์ด์ง ๋ฐ์ดํฐ๋ฅผ ์ ์กํด์ผํ ๋๋, ์ด์ง ๋ฐ์ดํฐ๋ฅผ ํ ์คํธ ํ์์ผ๋ก ์ธ์ฝ๋ฉํ๋ ๊ณผ์ ์ด ๋นํจ์จ์ ์ด๋ฉฐ ์ ํ์ ์ด๋ค.
- ๐ Multipart๋ ์ด๋ฌํ ์ด์ง๋ฐ์ดํฐ(ํ์ผ)์ ์ธ์ฝ๋ฉํ์ง ์๊ณ , ์๋ณธ ํ์ ๊ทธ๋๋ก ์ ์กํ ์ ์๋ค.
- ์ด๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด, HTTP Content-Type Header์ ‘multipart/form-data’ ํ์์ผ๋ก ์ ์กํ๋ฉด ๋๋ค.
๐ก Mutlipart Streaming ๋ฐฉ์์ ์ ์ฅ๋ฐฉ๋ฒ
- ์ ์ฒด ๋ฐ์ดํฐ ์์
- ์๋ฒ → ํด๋ผ์ด์ธํธ๋ก ์ ์ฒด ๋ฉํฐํํธ ๋ฐ์ดํฐ ์์
- ๋ฉ๋ชจ๋ฆฌ/๋์คํฌ์ ์ ์ฅ
- ์์ ๋ ๋ฐ์ดํฐ๋ฅผ ๋ฉ๋ชจ๋ฆฌ๋ ์์ ๋์คํฌ ํ์ผ์ ์ ์ฅ
- ๋ถ์ ๋ฐ ์ฒ๋ฆฌ
- ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ํ์ฑํ์ฌ ๊ฐ๋ณ ํํธ๋ก ๋ถ๋ฆฌํ๊ณ , ๊ฐ ํํธ๋ฅผ ์ฒ๋ฆฌ (multipart์ธ ์ด์ )
๐ก ํ๋ก์ ํธ ์ฝ๋ ๋ถ์ - AJAX๋ก ๊ตฌํ (FORM ํ๊ทธ X)
- uploadFile (AJAX)
function uploadFile() { let targetPathInput = document.getElementById("target_path"); const fileInput = document.getElementById('file-upload'); const file = fileInput.files[0]; const formData = new FormData(); formData.append('file', file); fetch('/upload-file', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { if (data.message.includes("์ฑ๊ณต")) { document.getElementById('file_path').value = data.data; targetPathInput.value = data.data; } else { alert('ํ์ผ ์ ๋ก๋ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค: ' + data.message); } }) .catch(error => { console.error('Error:', error); alert('ํ์ผ ์ ๋ก๋ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.'); }); }
- fetch์ body๋ฅผ formData๋ก ์ค์ ์, ์๋์ผ๋ก ํด๋น ๋ฐ์ดํฐ๋ฅผ multipart/form-data ํ์์ผ๋ก ์ธ์ฝ๋ฉํ์ฌ ์ ์กํ ์ ์๋ค.
- Service (back)
/** * ์ฌ์ฉ์์ ๋ก์ปฌ ํ์ผ์ ์๋ฒ์ ์ ์ฅ * * @param file ์ฌ์ฉ์์ ๋ก์ปฌ ํ์ผ */ public String saveFileInServer(MultipartFile file) { String saveFilePath = System.getProperty("user.dir") + TARGET_SAVE_PATH; String fileName = file.getOriginalFilename(); String fileNameWithoutExtension = fileName.substring(0, fileName.lastIndexOf(".")); String fullPath = saveFilePath + fileName; try { if(isValidDirectoryPath(fullPath)) { throw new DuplicatedFileException(ErrorCode.DUPLICATED_FILE_EXCEPTION); } if(!file.isEmpty() && isFileTar(fileName)) { file.transferTo(new File(fullPath)); } else if(!isFileTar(file.getOriginalFilename())) { throw new FailedToSaveLocalFileException(ErrorCode.NOT_TAR_EXTENSION); } return fileNameWithoutExtension; } catch (IllegalStateException | IOException e) { throw new FailedToSaveLocalFileException(ErrorCode.FAILED_TO_SAVE_LOCAL_FILE); } }
- AJAX๋ฅผ ํตํด ํธ์ถ๋ ๋, ์ฌ์ฉ์๊ฐ ์ ๋ก๋ํ MultipartFile ํ์ ์ ํ์ผ์ ๋งค๊ฐ๋ณ์๋ก ๊ฐ๋๋ค.
- ์ ์ฅํ๊ณ ์ ํ๋ ๊ฒฝ๋ก (fullPath)์ ์์ธ์ฒ๋ฆฌ์ ํด๋น๋์ง ์์ ๊ฒฝ์ฐ(์ณ์ ์กฐ๊ฑด) transfer๋ฅผ ํตํด ์ ์ฅํ๋ค.
'BACKEND > JAVA & SPRING' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์ ์บ์คํ , ๋ค์ด์บ์คํ ์ ๋ํด (3) | 2024.10.30 |
---|---|
๋ฒํฌ์ฐ์ฐ์ ํตํ update ์ฑ๋ฅ ๊ฐ์ ์๋ ๊ทธ๋ฆฌ๊ณ ์ผ๋ฐ ์ฐ์ฐ๊ณผ์ ๋น๊ต (0) | 2024.08.07 |
Transaction์ ์ ํ (feat. REQUIRES_NEW์ ๋ฌธ์ ์ ) (0) | 2024.07.31 |
[Spring Security + JWT + OAUTH2] ์นด์นด์ค/๋ค์ด๋ฒ ์ธ๋ถ ๋ก๊ทธ์ธ ๊ตฌํ (0) | 2024.04.30 |
HttpURLConnection์ ์ด์ฉํ API ๋ฐ์ดํฐ ๋ฐ์์ค๊ธฐ (1) | 2024.04.25 |