react&node.js 개발 -image 데이터 서버에 저장하는 방법 배우기
1. 이미지 데이터 저장?
관계형 데이터베이스 MySQL에 비정형 데이터인 이미지를 그냥 저장할 수는 없다
보통 이미지를 클라이언트에서 서버로 보내 저장할때,
이미지 위치 경로만 DB에 저장하고 실제 이미지 파일은 서버 내에 저장시킨다
2. input 태그
input태그에서 type='file'로 지정하면 파일을 업로드 받을 수 있다
<input
type="file"
accept="image/*"/>
accept 속성은 입력받을 파일의 형식을 지정
image/*하면 image 파일인데 확장자 jpg, png등 상관없다는 말
하지만 accept로 하더라도 다른 파일을 입력받을 수는 있다
특정 파일만 받게할 수는 있다고 하는데 당장 필요한건 아니니..
3. FileReader()
자바스크립트에서 FileReader() 객체를 이용해 파일을 읽어들일 수 있다
const saveImage = (e) => {
e.preventDefault();
const fileReader = new FileReader();
if (e.target.files[0]) {
console.log(e.target.files)
fileReader.readAsDataURL(e.target.files[0]);
}
fileReader.onload = () => {
setImage({
image_file: e.target.files[0],
preview_URL: fileReader.result,
});
};
};
....
return (
<div className="uploader-wrapper">
<input
type="file"
accept="image/*"
onChange={saveImage}
ref={(refParam) => (inputRef = refParam)}
style={{ display: "none" }}
/>
....
리액트에서 input태그의 onChange에 위 함수를 넣으면,
파일을 업로드받을때 e로 이벤트를 받아서, 생성한 filereader가 파일을 읽어들여 e.target.files로 받아온다
그럼 0번에 입력받은 파일이 있음
readAsDataURL은 이미지 같은 바이너리 파일을 읽어들일때 사용한다고함
그리고 onload 메소드는 성공적으로 파일을 읽어들였을때 발생
4. FormData
이미지같은 멀티미디어 파일을 페이지 전환 없이, 폼 데이터로 비동기 제출을 하고 싶거나, 잘 관리하고 싶을 때 사용한다고함
그러니까 이미지 파일을 서버에 전송시키고 싶으면 단순한 json보다는 FormData 객체로 전달하는게 나은듯
const formData = new FormData();
formData.append("title", title);
formData.append("content", content);
formData.append("file", image.image_file);
사용하는 방법은 위와 같이 new FormData()로 객체 생성하고, .append()메소드에 (key, value)로 넣어준다
formdata는 특수한 형태라 console.log로 찍어보면... 전송한 데이터가 잘 안보인다
그리고 axios로 전송해보면... 실제로 전송도 잘 안됨
app.post('/api/board',(req,res) => {
console.log(req.body)
})
실제로 보내서 서버 로그에 확인해보면.. 전송이 안됨
5. multer
서버에 전송할때 body-parser를 사용해왔는데 얘는 multipart bodies를 다루지 않아서 읽어오질 못한다고 한다
이를 위해 이미지를 받아오기 위해 주로 사용하는 모듈이 multer
$npm install multer로 설치
6. storage 작성
backend/storage.js를 생성하고 이미지 파일을 저장하기 위해 다음과 같이 작성
여기서 moment는 시간을 다루는 라이브러리로 npm install moment로 설치가능
//backend/storage.js
const multer = require('multer');
const moment = require('moment');
const storage = multer.diskStorage({
destination: function(req,file,cb) {
cb(null,'images'); //save image file directory
},
filename: function(req,file,cb) {
cb(null,moment().format('YYYYMMDDHHmmss')+'_'+file.originalname); //save image name
}
});
module.exports = storage;
destination에서 cb(null,'images')하면 서버 내 images 폴더에 이미지를 저장한다는 의미
filename은 가져온 파일을 어떤식의 이름으로 저장할지 지정함
저장시간과 원래 파일명을 조합해서 사용했다
7. 서버 작성
server.js에 다음과 같이 api 작성
const multer = require('multer')
const storage = require('./storage')
const upload = multer({storage:storage}).single('file'); //single: to use single file upload, array: to use multiple file upload
app.post('/api/board',upload,(req,res) => {
console.log(req.body)//save text data
console.log(req.file)//save file data
Board.create({
title: req.body.title,
content: req.body.content,
imageUrl: req.file.path,
user_id: Number(req.body.user_id)
})
.then(result => {
res.send(
{
title:req.body.title,
content:req.body.content,
imageUrl:req.file.path,
user_id:Number(req.body.user_id),
message:"게시판에 글을 작성하였습니다!"
}
)
})
.catch( err => {
console.log(err)
throw err;
})
})
multer를 불러오고, 작성한 storage를 불러온다.
const upload = multer({storage:storage}).single('file');으로 작성하면, 하나의 파일을 저장하겠다는 의미이다.
여기서 single('file')이 좀 중요한데, 'file'은 아무거나 작성하면 안된다.
formdata로 전송할때 이미지 파일이 들어간 key값을 작성해줘야함
const formData = new FormData();
formData.append("title", title);
formData.append("content", content);
formData.append("file", image.image_file);
서버로 보낼 데이터를 위와 같이 작성했다면, image가 들어간 key값은 file이라서 'file'로 작성해줘야 한다
그리고 app.post('/api/board', (req,res) => {})으로 하던걸 upload를 이용해서
app.post('/api/board', upload, (req,res) => {})으로 작성
이러면 req에서 req.body에는 text 데이터인 title, content가 저장되어 있고
req.file에는 이미지 데이터가 저장되어 있다
성공하면, backend에 만들어둔 images 폴더에 다음과 같이 이미지가 저장되어있다
참조
프론트에서 서버로 이미지 전송하기(HTML->multer-Express) (tistory.com)
[JS] 📚 FormData 사용법 & 응용 총정리 (+ fetch 전송하기) (tistory.com)
OKKY - Node.js에서 FormData가 undefined인 문제 해결좀 부탁드립니다 ㅠㅠ
React 이미지 파일 업로드 하기 (tistory.com)
[Node.js] Multer 파일 업로드 관련 에러: MulterError: Unexpected field (tistory.com)
JS - 파일API : FileReader() 객체 (habonyphp.com)
[HTML] input type='file' 속성 알아보기 ( 파일 입력 ) - 어제 오늘 내일 (tistory.com)
'프로그래밍 > node.js' 카테고리의 다른 글
react & node.js 개발 -static 이용해서 클라이언트에서 서버의 이미지 파일 접근하기- (0) | 2023.01.25 |
---|---|
react&node.js 개발 -python-shell이용해서 서버에서 python 프로그램 실행시키기- (0) | 2023.01.24 |
react&node.js 개발 - 로그인하면서 JWT 토큰 발급받고 유저 정보 알아내기 (0) | 2023.01.22 |
node.js 프로그래밍에서 axios 504에러날때 시도할부분 (0) | 2023.01.19 |
react와 express 서버 연동 익히기 9편 -DB 데이터 삭제하기- (0) | 2023.01.18 |