BASE64란 8비트 바이너리 데이터(예를 들어 실행파일이나, ZIP파일 등)를 문자 코드에 영향을 받지 않는 공통 ASCII 영역의 문자들로만 이루어진 일련의 스트링으로 바꾸는 인코딩 방식을 가리키는 개념입니다. 다시 말해서, 바이너리를 읽을 수 있는 스트링 형태로 바꾼 자료형을 BASE64라고 합니다. (자세한 설명)
예전에 스프링 부트에서 MultipartFile을 이용해 파일 업로드를 하는 방법에 대한 글을 쓴 적이 있습니다.
이 방법의 장점도 많겠지만 JSON을 통해 리퀘스트를 전송하고자 할 때 JSON 안에 포함하여 사용할 수 없다는 단점이 있었습니다. 일반 바이너리 파일을 BASE64로 변환하면 약 33%의 사이즈 증가가 있다고 하지만, 이미지 파일같은 작은 사이즈의 파일들은 @RequestBody를 통해 JSON에 포함해서 전송하면 MultipartFile을 별도로 처리해야 하는 불필요한 과정을 생략할 수 있습니다.
스프링 부트 컨트롤러
클라이언트로부터 인코딩된 BASE64 텍스트를 받은 뒤, 그것을 바이트 배열로 디코딩하여 FileOutputStream을 통해 파일을 생성합니다.
import javax.swing.filechooser.FileSystemView; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URLEncoder; import java.util.Base64;
@PostMapping("/api/upload")
public Map<String, Object> addData(@RequestBody DataDTO data) {
Map<String, Object> result = new HashMap<>();
String fileBase64 = data.getFileBase64();
// 파일이 업로드되지 않았거나 사이즈가 큰 경우를 체크합니다.
// 사이즈는 일반 바이트에서 1.33을 곱하면 BASE64 사이즈가 대략 나옵니다.
if(fileBase64 == null || fileBase64.equals("")) {
result.put("isFileInserted", false);
result.put("uploadStatus", "FileIsNull");
return result;
} else if(fileBase64.length() > 400000) {
result.put("isFileInserted", false);
result.put("uploadStatus", "FileIsTooBig");
return result;
}
try {
String fileName = data.getFileName(); // 파일네임은 서버에서 결정하거나 JSON에서 받아옵니다.
// 저장할 파일 경로를 지정합니다.
File file = new File(FileSystemView.getFileSystemView().getHomeDirectory()
+ "/app/resources/" + fileName);
// BASE64를 일반 파일로 변환하고 저장합니다.
Base64.Decoder decoder = Base64.getDecoder();
byte[] decodedBytes = decoder.decode(fileBase64.getBytes());
FileOutputStream fileOutputStream = new FileOutputStream(file);
fileOutputStream.write(decodedBytes);
fileOutputStream.close();
result.put("isFileInserted", true);
result.put("uploadStatus", "AllSuccess");
} catch(IOException e) {
System.err.println(e);
result.put("uploadStatus", "FileIsNotUploaded");
result.put("isTTSInserted", false);
}
return result;
}
참고로 DataDTO 구조는 다음과 같습니다.
public class DataDTO {
private Long id;
private String fileName;
private String fileBase64;
// ...... 이하 생략 (Getter/Setter 등) ......
자바스크립트
파일을 보내는 쪽에서 BASE64로 인코딩 한 다음 보내야 합니다.
let encodedFile, originalFileName
function handleFile(e) {
const files = e.target.files
if(files.length > 0) {
const file = e.target.files[0]
originalFileName = file.name
if(file.size > 300000) {
alert("파일 사이즈가 너무 큽니다.")
return false
}
// FileReader를 사용해 BASE64로 변환합니다.
const reader = new FileReader()
// FileReader가 파일을 load했을 시 동작할 이벤트를 지정합니다.
reader.addEventListener("load", () => {
const dataIndex = reader.result.indexOf(',') + 1
const base64 = reader.result.substring(
dataIndex,
reader.result.length
)
encodedFile = base64
})
// file을 DataURL 형식으로 읽습니다.
reader.readAsDataURL(file)
}
}
async function sendData() {
if(!encodedFile) {
alert("파일이 없습니다.")
return false
}
const dataObj = {
fileBase64: encodedFile,
fileName: originalFileName
}
const initFetch = await fetch("/api/upload", {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(dataObj)
})
const data = await initFetch.json()
// 결과 JSON 받은 후 동작
}
JSON 업로드 예제
Request JSON 일부

서버로부터 응답 결과
![]()





0개의 댓글