Spring Boot, Multipart 파일 업로드 구현하기

먼저 읽어볼만한 글

라이브러리 종속성 추가

/build.gradle 파일에 아래 내용을 추가한다.

dependencies {
    compile group: 'org.projectlombok', name: 'lombok', version: '1.16.8'
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.4'
    compile group: 'commons-io', name: 'commons-io', version: '2.5'
}
  • Multipart 처리와 직접적인 연관은 없지만 간결한 예제 소스 코드 작성을 위해 필요한 라이브러리를 프로젝트에 추가하였다.

환경설정

/src/main/resources/application.properties 파일에 아래 내용을 추가한다.

multipart.maxFileSiz=1MB
multipart.maxRequestSize=1MB
  • 파일 업로드 목적의 HTTP 요청시 헤더의 Content-Typemultipart/form-data이어야 한다.
  • Spring Boot에서 Multipart 요청을 처리하려면 multipartConfigElement, multipartResolver 이름의 빈이 애플리케이션 컨텍스트에 존재해야 한다. 애플리케이션 시작시 MultipartAutoConfiguration 클래스가 이 작업을 자동으로 수행한다.
  • multipart.maxFileSize는 업로드 가능한 최대 파일 크기, multipart.maxRequestSize는 업로드 가능한 총 요청 크기이다. 이 조건을 초과한 요청이 들어오면 MultipartException을 발생시킨다.

컨트롤러 작성

/src/main/java/com.jsonobject.example/AttachmentController.java 파일을 아래와 같이 작성한다.

package com.jsonobject.example;

import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@RestController
@RequestMapping("/attachments")
public class AttachmentController {

    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<?> uploadAttachment(@RequestPart MultipartFile sourceFile) throws IOException {

        String sourceFileName = sourceFile.getOriginalFilename();
        String sourceFileNameExtension = FilenameUtils.getExtension(sourceFileName).toLowerCase();

        File destinationFile;
        String destinationFileName;
        do {
            destinationFileName = RandomStringUtils.randomAlphanumeric(32) + "." + sourceFileNameExtension;
            destinationFile = new File("C:/attachments/" + destinationFileName);
        } while (destinationFile.exists());
        destinationFile.getParentFile().mkdirs();
        sourceFile.transferTo(destinationFile);

        UploadAttachmentResponse response = new UploadAttachmentResponse();
        response.setFileName(sourceFile.getOriginalFilename());
        response.setFileSize(sourceFile.getSize());
        response.setFileContentType(sourceFile.getContentType());
        response.setAttachmentUrl("http://localhost:8080/attachments/" + destinationFileName);

        return new ResponseEntity<>(response, HttpStatus.OK);
    }

    @NoArgsConstructor
    @Data
    private static class UploadAttachmentResponse {

        private String fileName;

        private long fileSize;

        private String fileContentType;

        private String attachmentUrl;
    }
}
  • sourceFile 이름으로 요청 받은 파일을 로컬 디스크에 복사 후 접근 가능한 URL을 포함한 파일 정보를 JSON으로 응답하는 간단한 기능이다.

  • MultipartFile.transferTo()는 요청 시점의 임시 파일을 로컬 파일 시스템에 영구적으로 복사하는 역할을 수행한다. 단 한번만 실행되며 두번째 실행부터는 성공을 보장할 수 없다. Embedded Tomcat을 컨테이너로 사용할 경우 DiskFileItem.write()가 실제 역할을 수행한다. I/O 사용을 최소화하기 위해 파일 이동을 시도하며, 이동이 불가능할 경우 파일 복사를 진행한다.

저작자 표시 비영리 동일 조건 변경 허락
신고