Back-End/Spring

[React, Spring] 서버에 MultipartFile 업로드(Axios POST 사용)

유자맛바나나 2022. 1. 26. 03:18

 

[Front-End Side] Axios POST를 이용해 File 업로드 요청

 

1. 파일을 주고받을 때는 Multipart/form-data 타입을 이용한다.

1.1. HTTP Headers에 타입 추가

아래와 같이 headers에 'multipart/form-data'를 추가한다.

axios({
  ...
  headers: {
    'Content-Type': 'multipart/form-data',
  },
});

 

1.2. JavaScript의 FormData 객체를 생성해 데이터로 전달한다.

FormData 인터페이스는 Key/Value 쌍으로 데이터를 쉽게 생성/삭제할 수 있는 방법을 제공한다.

★중요★

하나의 Key에 Value를 'List 형태'로 여러 개를 보내고 싶을땐 동일한 Key에다 계속 append 해준다. Java에서는 List<Type>과 Mapping 된다. 

const formData = new FormData();

formData.append('inputFile', file1); // File 타입 객체 첨부
formData.append('inputStr', str); // String 같은 타입도 첨부 가능

// ★중요★ 하나의 Key(inputFileList)에 List 형태로 여러 개의 value 전달 가능
formData.append('inputFileList', file2);  
formData.append('inputFileList', file3);
formData.append('inputFileList', file4);

 

[Reference] MDN Web Docs - JavaScript FormData 인터페이스

https://developer.mozilla.org/ko/docs/Web/API/FormData

 

2. 완성된 Axios POST 요청 Code

const saveFileRequest = () => {
  const formData = new FormData();
  formData.append('inputFile', fileObject1); // File 타입 객체 첨부
  formData.append('inputStr', strObject); // String 타입 첨부

  // ★중요★ 하나의 Key(inputFileList)에 List 형태로 여러 개의 value 전달 가능
  formData.append('inputFileList', fileObject2);  
  formData.append('inputFileList', fileObject3);
  formData.append('inputFileList', fileObject4);

  axios({
    method: 'post',
    url: 'http://localhost:8080/file-import',
    headers: {
      'Content-Type': 'multipart/form-data',
    },
    data: formData,
  }).then(response => {...});
};

[주의] Axios의 data에는 FormData 객체를 그대로 전달한다

처음에 헤매면서 시간 낭비를 한 부분이다. 아래와 같이 작성하지 않도록 주의하자!

 

잘못된 예시 1) JSX 문법으로 착각

axios({
  ...
  data: {formData},
}};

잘못된 예시 2) Object의 Key와 @RequestParam이Mapping 된다고 착각 (★특히 오랫동안 헤맸던 부분★)

axios({
  ...
  data: {inputFile: formData} // "inputFile"을 Spring의 RequestParam("inputFile")과 Mapping된다고 착각
}};

 

[참고] Axios의 headers 자동 생성

axios의 data 속성에 전달되는 객체가 FormData일 경우 headers에 'Content-Type': 'multipart/form-data'를 명시하지 않아도 자동으로 추가한다

 

 

[Back-End Side] @RequestParam, MultipartFile 인터페이스로 Mapping

@PostMapping(
        value = "/file-import",
        consumes = MediaType.MULTIPART_FORM_DATA_VALUE
)
public void saveScenarioFile(@RequestParam("inputFile") MultipartFile file,
                             @RequestParam("inputStr") String str),
                             @RequestParam("inputFileList") List<MultipartFile> fileList) {
    
    ...
}
  • consumes
    들어오는 데이터 타입을 강제할 때 사용된다. 즉, 위에 작성된 consumes 부분은 Multipart form-data로 강제하는 것을 볼 수 있다.  따라서 HTTP headers의 'Content-Type'에 명시되지 않으면 에러가 발생한다. 강제할 때 사용하는 것이므로 제거해도 정상적으로 작동한다.
  • @RequestParam("Key")와 FormData 객체의 Key Mapping
    [2. 완성된 Axios POST 요청 Code] 코드에서 formData에 데이터를 추가할 때 Key/Value 쌍으로 추가했다. 이 때 추가한 Key - inputFile, inputStr를 @RequestParam("inputFile"), @RequestParam("inputStr")과 같이 작성해 Mapping 시킨다
  • MultipartFile
    Front-End에서 전달받을 File은 MultipartFile 인터페이스 타입으로 받는다.

 

[참고] MultipartFile 객체 파일을 서버 PC에 쉽게 저장하기

MultipartFile 객체는 객체에 담긴 데이터를 Java의 File로 쉽게 converting 해주는 trasferTo() 메서드를 제공한다. 아래와 같이 코드를 작성하면 PC에 파일이 생성된다.

public void saveScenarioFile(@RequestParam("inputFile") MultipartFile file,
                             @RequestParam("inputStr") String str),
                             @RequestParam("inputFileList") List<MultipartFile> fileList) {
    
   try {
      File file = new File("원하는 디렉토리 경로" + inputFile.getOriginalFilename());
      inputFile.transferTo(file);
   } catch (IOException e) {
      e.printStackTrace();
   }
}

 

 

[References]Spring에서 MultipartFile 타입을 받는 세 가지 방법(읽어보기)

https://caileb.tistory.com/152

 

MultipartFile을 사용한 File 업로드 (multipart/form-data)

MultipartFile을 사용한 File 업로드 (multipart/form-data) SpringFramework환경의 서버라면 SpringFramework에서 제공하고 있는 MultipartFile 클래스와 MultipartHttpServletRequest 클래스를 사용해서..

caileb.tistory.com

consumes, produces

https://mungto.tistory.com/438

 

[Spring] consumes와 produces의 차이

Mapping을 할때 우리는 받고싶은 데이터를 강제를 함으로써 오류상황을 줄일 수 있다. 이걸 위해 사용하는 것 중 하나가 Media Types이다. 들어오는 데이터와 나가는 데이터를 정하여 처리를 할 수 있

mungto.tistory.com

MultipartFile to File

https://kkumalog.tistory.com/74

 

[JAVA] Converting MultipartFile to File

이 페이지에서는 멀티파트파일을 파일객체로 변환하는 방식에 대해 설명하고 있다. # MultipartFile vs File 변환하는 코드 작성에 앞서 두 객체에 대해 간단하게 설명하려한다. 1) MultipartFile 멀티파트

kkumalog.tistory.com