클라이언트의 이미지를 AWS의 S3, Naver Cloud Platform의 Object Storage 같은곳에 업로드 하기 위해서는 Multer와 Multer-S3 모듈이 필요하다.
일단은 글쓰기 기능에서 이미지 업로드 기능을 추가하는 작업을 했다. 큰 틀은 제출 버튼을 누르면 imageupload(Object Storage에 이미지 업로드), write(db에 글의 내용 업로드)두개의 post를 요청한다
이미지 이름의 중복을 방지하기위해서 Date.now() + "_" + fileName 과 같이 시간함수로 랜덤한 숫자를 앞에 붙여주는 방식을 사용했다.
db에 글의 내용을 업로드 해주는 write는 먼저 HTML의 Form, Form Submit을 이용해 전송하도록 작성을 했고
그 뒤에 추가로 작성한 imageupload는 fetch를 이용해 작성했다.
write로 데이터를 보낼때 기존 파일명에 시간함수를 붙인 새로운 파일명(이하 nickname)을 전송해야하지만 폼을 이용한 전송은 해당 페이지에 존재하는 요소들 외에 추가적으로 따로 설정해둔 변수를 전송할 수 없다는 점 때문에 "\<input type="text" hidden/>" 을 이용해 보이지 않는 input box를 이용해 해당 요소에 nickname을 저장해 전송하기로 했다.
Fetch를 이용해 FormData 를 전송하기위해서
const formData =new FormData();
formData.append('nickname', imgName);
formData.append('img', fileField.files[0]); 와 같은 코드를 이용해서 폼 데이터를 만들어주고 fetch할때 body에 form 데이터를 첨부하는 식으로 전송한다.
fetch('http://localhost:4000/board/imageupload', {
method: 'post',
body: formData,
});
이때 기존에 fetch의 헤더에 Content-Type을 기입해줬었는데 특정 이유 때문에 폼데이터를 전송할 시에는 헤더를 {}로 작성하거나 헤더 자체를 포함하지 않으면 정상 작동한다.
이유는 헤더에 자동으로 boundary값이 붙기 때문이라고 한다.
관련 자료 링크
https://muffinman.io/uploading-files-using-fetch-multipart-form-data/
https://gaemi606.tistory.com/38
https://os94.tistory.com/125
multer-s3을 이용해 이미지 업로드를 수행할 시에 이전에 formData에 nickname을 추가했는데 multer에 전달받은 req의 body에 데이터가 없는 문제가 발생했다.
이리저리 검색한 결과
"이미지 파일"보다 다른 데이터가 앞에 위치해야한다. 즉 img를 맨 마지막에 append 해야한다는 뜻.
즉,
const formData =new FormData();
formData.append('img', fileField.files[0]);
formData.append('nickname', imgName); 이 아닌
const formData =new FormData();
formData.append('nickname', imgName);
formData.append('img', fileField.files[0]); 와 같이 작성해야함
이유는 multer가 먼저 들어온 img를 처리하고 그 이후에 데이터를 받아오기 때문인 것 같다.
관련 자료 링크
https://github.com/expressjs/multer/issues/322
https://github.com/expressjs/multer/issues/146