개발/JAVA

파일 조각 업로드 (Chunked Upload)

소금집사 2025. 1. 7. 13:22
반응형

HTTP 방식의 파일 업로드 도중 중단되었을 때 나중에 이어서 업로드하는 기능을 구현하려면 파일 조각 업로드(chunked upload) 방식이나 비동기 파일 업로드 방식 등을 고려할 수 있습니다.

1. 파일 조각 업로드 (Chunked Upload)

파일을 작은 조각으로 나누어 업로드하는 방식입니다. 중단되었을 때, 이미 업로드된 부분은 그대로 두고, 중단된 부분부터 다시 업로드를 시작할 수 있습니다.

  • 클라이언트 측: 파일을 일정 크기(예: 1MB)로 분할하여 업로드합니다. 각 조각은 순차적으로 서버로 전송되며, 서버는 각 조각을 받고 저장합니다.
  • 서버 측: 각 파일 조각을 수신하여 임시 디렉터리에 저장하고, 모든 조각이 업로드되면 이를 하나로 합쳐서 최종 파일을 생성합니다.
  • 중단 처리: 클라이언트가 중단된 지점부터 다시 업로드할 수 있도록, 서버는 각 조각의 업로드 상태를 추적해야 합니다.

2. HTTP Range 요청

HTTP의 Range 헤더를 사용하여 파일의 일부를 요청하고 업로드할 수 있습니다. 이 방법을 사용하면 클라이언트가 중단된 부분부터 업로드를 재개할 수 있습니다.

  • 클라이언트 측: 처음에 업로드된 바이트의 범위를 서버에 전달하고, 그 이후에 계속해서 업로드를 진행할 수 있습니다.
  • 서버 측: 서버는 각 범위에 대해 데이터를 받아서 저장하고, 파일이 완성되면 최종적으로 하나의 파일로 결합합니다.

3. 비동기 파일 업로드와 재시도 로직

업로드가 중단되었을 때 클라이언트 측에서 자동으로 재시도를 시도하는 로직을 추가할 수 있습니다. 특히 네트워크 문제로 인한 중단에 대비해, 업로드 중인 파일의 상태를 체크하고 실패하면 재시도하는 방식입니다.

  • 클라이언트 측: 업로드 진행 상태를 추적하고, 네트워크 장애나 중단 시 자동으로 다시 연결하여 이전에 업로드된 부분부터 이어서 진행합니다.
  • 서버 측: 각 업로드의 상태를 저장하고, 클라이언트가 이어서 업로드할 수 있도록 이미 업로드된 부분을 파악할 수 있어야 합니다.

구현 예시

  • 클라이언트 측 (JavaScript 예시):
function uploadFile(file) {
    const chunkSize = 1024 * 1024; // 1MB
    let start = 0;

    function uploadChunk() {
        const end = Math.min(start + chunkSize, file.size);
        const chunk = file.slice(start, end);
        const formData = new FormData();
        formData.append('file', chunk, file.name);
        formData.append('start', start);

        fetch('/upload', {
            method: 'POST',
            body: formData
        }).then(response => {
            if (response.ok) {
                start = end;
                if (start < file.size) {
                    uploadChunk(); // Next chunk
                }
            } else {
                // Handle error (retry logic, etc.)
            }
        });
    }

    uploadChunk(); // Start uploading chunks
}
  • 서버 측 (Spring Boot 예시):
@PostMapping("/upload")
public ResponseEntity<String> uploadFile(
    @RequestParam("file") MultipartFile file,
    @RequestParam("start") long start) throws IOException {

    Path tempFile = Paths.get("/uploads", file.getOriginalFilename());
    Files.write(tempFile, file.getBytes(), StandardOpenOption.CREATE, StandardOpenOption.APPEND);

    // Handle chunk status (e.g., store information about the chunk that was uploaded)
    return ResponseEntity.ok("Chunk uploaded successfully.");
}

이 방법을 사용하면 파일이 중단되더라도 업로드를 이어서 진행할 수 있습니다.

반응형