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)

 

프론트에서 서버로 이미지 전송하기(HTML->multer-Express)

들어가기 프론트에서 백엔드로 이미지를 전송하는 방법을 알아보겠습니다. 이 게시글에서 정리한 방법은 'html단에서 express.js 서버에 어떻게든 이미지 파일을 보내서 저장시키고 싶다!'라는 사

meir.tistory.com

 

[JS] 📚 FormData 사용법 & 응용 총정리 (+ fetch 전송하기) (tistory.com)

 

[JS] 📚 FormData 사용법 & 응용 총정리 (+ fetch 전송하기)

FormData API 보통 서버에 데이터를 전송하기 위해서는 HTML5 의 폼 태그를 사용해 다음과 같이 메뉴를 구성하여 제출 해본 기억들이 있을 것이다. 아이디 비밀번호 성별 남자 여자 응시분야 영어 수

inpa.tistory.com

 

OKKY - Node.js에서 FormData가 undefined인 문제 해결좀 부탁드립니다 ㅠㅠ

 

OKKY - Node.js에서 FormData가 undefined인 문제 해결좀 부탁드립니다 ㅠㅠ

Node.js Express 로 웹 서버 구축해놓고 React 페이지에서 axios 사용해서 값을 보냈습니다. 아래는 전송 버튼을 눌렀을 떄 React 페이지에서 값 보내는 함수 부분입니다.  그리고 아래처럼 F12 눌러봤을

okky.kr

 

 

React 이미지 파일 업로드 하기 (tistory.com)

 

React 이미지 파일 업로드 하기

React로 파일을 업로드 방법을 정리하려고합니다. 간단한 방법은 아래와 같습니다. 클라이언트 앱(react) view 페이지에서 input[type=file] 요소를 적절한 위치에 추가. state 추가( state를 이용해서 파일

basketdeveloper.tistory.com

 

[Node.js] Multer 파일 업로드 관련 에러: MulterError: Unexpected field (tistory.com)

 

[Node.js] Multer 파일 업로드 관련 에러: MulterError: Unexpected field

# Node.js - MulterError: Unexpected field 해결 방법 Node.js 에서 Multer 를 통해서 파일을 업로드 받을 때, 아래와 같은 에러가 발생할 수 있다. [에러 코드] MulterError: Unexpected field code: 'LIMIT_UNEXPECTED_FILE', storag

curryyou.tistory.com

 

JS - 파일API : FileReader() 객체 (habonyphp.com)

 

JS - 파일API : FileReader() 객체

무료로 사용할 수 있는 CMS 형 PHP 버드 패널, 테마, FTP 외 라이브러리 제공

www.habonyphp.com

 

[HTML] input type='file' 속성 알아보기 ( 파일 입력 ) - 어제 오늘 내일 (tistory.com)

 

[HTML] input type='file' 속성 알아보기 ( 파일 입력 )

웹페이지에서 사용자의 로컬 파일을 입력받기 위해서는 다음과 같이 input 태그의 type속성을 file로 지정하는 방법을 사용합니다. See the Pen read file by anna (@hianna) on CodePen. 여기에서는 input의 type을 '

hianna.tistory.com

 

 

TAGS.

Comments