파일 요청 및 업로드

kangking·2024년 6월 25일
0

Spring Boot

목록 보기
7/10

HTTP요청으로 파일 받기

요청에 파일 포함 여러 값이 넘어올 경우

form-data 형식으로 Key Value 값이 여러개 넘어온다.
이 경우 텍스트만 넘어왔을 때와는 요청을 다르게 처리해야한다.

기존의 요청을 처리하던 컨트롤러 코드는 위와 같이 Body에 담긴 내용을 @RequestBody 어노테이션이 붙은 객체에 받아온다.

하지만 요청으로 보내려는 내용이 여러개이고 형식도 다르다면 HTTP 요청의 내용이 여러 파트로 나눠서 오기 때문에 받을 때도 파트별로 나눠 받아야 한다.

@RequestPart 어노테이션을 통해 여러 파트로 나눠오는 바디의 내용을 각각의 객체에 나눠 담을 수 있다.


파일 업로드

Service 구성 방식

기능별로 생성

  • 기능별로 필요할 때마다 Service 생성

의존성 주입이 자동으로 이루어지지만 컨트롤러가 수정될 가능성이 있다는 단점이 있다.

인터페이스 생성 후 구현

  • 파일업로드 서비스 인터페이스

  • 로컬에 저장하는 서비스 (인터페이스 상속)

  • 클라우드에 저장하는 서비스 (인터페이스 상속)

인터페이스를 구현하면 이름 그대로 메소드 구현 내용만 바뀌기 때문에 컨트롤러나 다른 코드들이 수정될 필요가 거의 없다는 장점이 있지만, 구현체가 여러개일 경우 의존성 주입시 어떤 구현체를 주입받을 것인지 명시해야 한다는 단점이 있다.

  • @Qualifier(클래스명)

    인터페이스(부모)타입으로 자식을 의존성 주입 받을 때, 스프링은 이것까지 구분해서 주입해주지는 못한다. 하지만 각각의 서비스에 @Qualifier으로 클래스명을 명시해주고 의존성 주입시점(생성자 등)에 @Qualifier를 명시하면 해당 객체의 bean으로 의존성을 주입받을 수 있다.

    하나의 인터페이스를 상속받는 서비스가 여러개라면
    위처럼 인터페이스 타입으로 의존성을 주입받을 때 어떤 서비스를 줄지 스프링은 모른다.
    따라서 위와 같이 의존성 주입때 사용할 객체를 명시해줄 수 있다.
    의존성을 주입할 때 (생성자)도 받아올 객체를 명시해준다.

파일 저장시 이름에 uuid(범용 고유 식별자)를 붙여서 동시에 저장되는 파일을 처리한다.

로컬 저장 코드

  • 인터페이스에서 상속받은 upload 구현메소드

    public String upload(MultipartFile file) {
            return saveFile(file);
        }
  • 디렉토리 생성 메소드

    public String makeFolder() {
    
            String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
    
            String folderPath = date.replace("/", File.separator);
            folderPath = uploadPath + File.separator + UUID.randomUUID()+folderPath;
    
            File uploadPathFolder = new File(folderPath);
            if(uploadPathFolder.exists() == false) {
                uploadPathFolder.mkdirs();
            }
    
            return folderPath;
        }
  • 파일 저장 메소드

    public String saveFile(MultipartFile file) {
            String originalName = file.getOriginalFilename();
    
            String folderPath = makeFolder();
    
            String saveFileName = folderPath+ File.separator + originalName;
            File saveFile = new File(saveFileName);
    
            try {
                file.transferTo(saveFile);
                return saveFileName;
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
    
        }
  • 컨트롤러에서 호출

    @PostMapping("/create")
       public ResponseEntity<String> create(
               @RequestPart ProductCreateReq dto,
               @RequestPart(name = "file") MultipartFile file
               ){
           String res = "";
           try {
               String filename = fileUploadService.upload(file);
               res = productService.create(dto,filename);
           }catch (Exception e){
               res = "등록 실패";
           }
    
           return ResponseEntity.ok(res);
    
       }
profile
하루하루 의미있게

0개의 댓글