이 게시글에선 dropzone을 통해 파일을 올리면 그 파일을 백엔드에서 multer라는 라이브러리를 이용해서 저장해주고, 그 저장해준 파일의 정보를 프론트로 갖고 올 것이다.
onDrop Function 만들기
import React from 'react'
import Dropzone from 'react-dropzone'
import {Icon} from 'antd'
import axios from 'axios'
function FileUpload() {
const dropHandler = (files) => {
let formData = new FormData();
const config = {
header: {'content-type': 'multierpart/form-data'}
}
formData.append("file", files[0])
axios.post('/api/product/image', formData, config)
.then(response => {
if (response.data.success) {
} else {
alert('파일을 저장하는데 실패하였습니다.')
}
})
}
return (
<div style={{display:'flex', justifyContent: 'space-between'}}>
<Dropzone onDrop={dropHandler}>
{({getRootProps, getInputProps}) => (
<section>
<div style={{width:300, height:240, border:'1px solid lightgray', display:'flex', alignItems:'center', justifyContent:'center'}}
{...getRootProps()}>
<input {...getInputProps()} />
<Icon type="plus" style={{fontSize: '3rem'}} />
</div>
</section>
)}
</Dropzone>
</div>
)
}
export default FileUpload
FileUpload.js
위 코드에서
let formData = new FormData();
const config = {
header: {'content-type': 'multierpart/form-data'}
}
formData.append("file", files[0])
이 부분을 봐보자.
엑시오스로 서버에 요청을 보낼 때 위 부분을 같이 보내지 않으면 에러가 난다.
multipart가 생긴 배경
기본적으로 form이 submit 되면 HTTP 헤더에 지정한 타입의 데이터가 Body에 담겨서 서버로 보내지게 됩니다.
정리하면 다음과 같습니다.
- HTTP Request의 Body에 클라이언트가 전송하려는 데이터가 담김
- Body에 들어가는 데이터의 타입을 HTTP Header에 명시해 줌으로써 서버가 타입에 따라 알맞게 처리
- 해당 Body의 타입을 명시하는 Header가 Content-Type
이때 중요한 점은 HTTP Request의 Body가 한 종류의 타입이 대부분이라는 점입니다.
Content-Type도 한 종류만 명시할 수 있는데 예를 들어 text이면 text/plain, xml이면 text/xml, png이미지이면 image/png 이런 식으로 명시하여 데이터를 서버로 전송하게 됩니다.
하지만 파일 업로드의 상황을 살펴보면 사진을 업로드하는 경우 사진에 대한 설명을 위한 input과 사인 파일을 위한 input 2개가 들어갑니다.
위 두 input에 대한 Content-Type은 전혀 다른데, 이미지의 설명에 대한 Content-Type은 application/x-www-form-urlencoded일 것이고, 사진 파일에 대한 Content-Type은 image/png 일 것입니다.
두 종류에 대한 Content-Type이 하나의 HTTP Request Body에 들어가야 하는데 이때 2종류의 데이터를 구분해서 넣어주는 방법이 필요해서 multipart라는 개념이 들어가게 되었습니다.
https://velog.io/@shin6403/HTTP-multipartform-data-%EB%9E%80
https://jw910911.tistory.com/117
여기까지했다면 일단 프론트 부분은 완성했다.
다음은 서버 부분을 구현해줘야한다.
여기서 한가지 알아야될 점이 있다.
프론트 코드를 보면
axios.post('/api/product/image', formData, config)
app.use('/api/users', require('./routes/users'));
app.use('/api/product', require('./routes/product'));
server/index.js
index.js에 위 코드에서 product 부분을 추가해주게 되면, 서버에서 요청을 받을 때 api product를 타고서 routes/product.js 파일로 가게된다. 그래서 routes.js 파일에서 요청 부분을 구현할 때 엔드포인트가 '/api/product/image' 이런식이 아니라 '/image' 이런식으로 구현해주면 된다.
const express = require('express');
const router = express.Router();
//=================================
// Product
//=================================
router.post('/image', (req, res) => {
// 가져온 이미지를 저장 해주는 부분
})
module.exports = router;
server/routes/product.js
이미지를 저장할 때 multer라는 것을 사용해야해서 multer 라이브러리를 다운받자. (multer은 server dependency임)
'react-shop-web > front & back' 카테고리의 다른 글
이미지 지우기 & 이미지 State를 부모 컴포넌트로 업데이트 하기 (0) | 2023.01.23 |
---|---|
multer를 이용하여 이미지 저장 (0) | 2023.01.22 |
Drop-Zone 적용하기 (0) | 2023.01.14 |
Select Option 처리하기 (0) | 2023.01.14 |
업로드 페이지 만들기 (0) | 2023.01.10 |