React, Next, Redux/⚛ React.JS
react + multer-s3 이미지 전송
DarrenKwonDev
2020. 7. 22. 04:02
https://darrengwon.tistory.com/91
https://darrengwon.tistory.com/317
1. 제출 버튼이 아니라 label을 눌러 버튼 형식으로 업로드하는 방식을 쓰려면 DOM을 조작해서 가상으로 제출 버튼을 누르게 만들어야 합니다.
(지금 생각해보니 이럴 때 쓰라고 있는게 useRef더군요... 아래 코드는 직접 DOM을 조작하는 방식으로 해버렸습니다만, 실전에선 재사용성을 위해 useRef를 사용합시다.)
2. formData로 전송해야 multer가 알아 듣습니다.
// 포토를 바꿨을 때, 제출을 위해 nextSibling을 DOM으로 불러 제출합니다.
const photoChange = (e) => {
e.target.nextSibling.click();
};
// 제출되었을 때의 로직
const PhotoSubmit = (e) => {
e.preventDefault();
// formData로 전송해야 multer가 알아 듣습니다.
const formData = new FormData();
formData.append("file", e.target.childNodes[1].files[0]);
axios.post("/api/image/profile", formData, {
header: {
"content-type": "multipart/form-data",
},
});
};
<form
encType="multipart/form-data"
style={{ position: "relative" }}
onSubmit={PhotoSubmit}
>
<Label htmlFor="file">이미지 변경</Label>
<input
type="file"
name="file"
id="file"
accept="image/*"
onChange={photoChange}
required
style={{ visibility: "hidden" }}
/>
<input type="submit" style={{ display: "none" }}></input>
</form>
3. file이라는 키 값으로 전송했으므로 multer에서는 file이라는 이름으로 받으면 되겠습니다. single("file")
const uploadUserProfileImage = multer({
storage: multerS3({
s3,
bucket: "cienps/user-profile-image",
contentType: multerS3.AUTO_CONTENT_TYPE,
acl: "public-read-write",
shouldTransform: true,
transforms: [
{
id: "user-image-resized",
key: function (req, file, cb) {
let extension = path.extname(file.originalname);
cb(null, Date.now().toString() + extension);
},
transform: function (req, file, cb) {
cb(null, sharp().resize(200, 200));
},
},
],
}),
}).single("file");
끝! 업로드된 내용은 req.file에 전달됩니다.
apiRouter.post("/image/profile", uploadUserProfileImage, (req, res, next) => {
console.log("uploaded", req.file);
});