본문 바로가기
Server/Node.js

이미지 업로드 해보기

by print_soo 2023. 9. 11.

1. 이미지를 업로드하는 페이지 만들기

 

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
  <!-- <link rel="stylesheet" href="public/main.css"> -->

  <script src="https://kit.fontawesome.com/f8ad50bee4.js" crossorigin="anonymous"></script>
  <title></title>
</head>

<body>

    <!--nav 부분 조립식으로 include하기 -->
    <%- include('nav.html')  %>

      
    <div class="container mt-2 ">
        <h4>업로드 페이지</h4>
        <br>
        <form method="POST" action="/upload" enctype="multipart/form-data">
            <input type="file" name="profile">
            <button type="submit"> 전송 </button>
        </form>
      </div>

      

    <!-- EJS:  html을 쓰기 쉽게 도와주는 전처리 엔진(라이브러리)-->

    <!-- jQeury install -->
    <!-- <script src="https://code.jquery.com/jquery-3.7.0.min.js"
    integrity="sha256-2Pmvv0kuTBOenSvLm6bvfBSSHrUJ+3A7x6P5Ebd07/g=" crossorigin="anonymous"></script> -->
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script>

    </script>

  <!-- JavaScript -->
  <!-- <script src="main.js"></script> -->


  <!-- bootstrap install -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
    integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous">
    </script>

</body>

</html>

 

해당 코드의 form을 보면 enctype이라고 우리가 이전에 보지 못한 속성이 있다.  이 속성은 뭘까?

 

enctype이란?

폼 데이터(form data)가 서버로 제출될 때 해당 데이터가 인코딩되는 방법을 명시해주는 속성이다.

 

enctype에 설정할 수 있는 아래 3개의 항목이 있다

  • application/x-www-form-urlencoded : 기본값으로, 모든 문자들은 서버로 보내기 전에 인코딩됨을 명시함.
  • multipart/form-data : 모든 문자를 인코딩하지 않음을 명시함. /  파일이나 이미지를 서버로 전송할 때 주로 사용함.
  • text/plain : 공백 문자(space)는 "+" 기호로 변환하지만, 나머지 문자는 모두 인코딩되지 않음을 명시함.

 

2. 페이지 라우팅해주기

app.get('/upload', function(request, response){
    response.render('upload.ejs')
})

 

3. 업로드한 이미지 저장하기

 사용자가 이미지를 업로드하면 보통 작업폴더 안에 저장시킨다. DB에 저장해도 되지만 용량이 크고 일반하드에 저장하는게 비용적으로 저렴하다. 따라서 보통 하드를 빌려서 거기에 저장을 한다.

 

따라서 우리는 우리 컴퓨터를 하드로 사용할 것이기 때문에 우리 프로젝트에 작업폴더를 하나 만들어준다. 

public 내부에 image 폴더를 만들어준다. 

이제 업로드하기 위해서 라이브러리를 설치하고 사용해보자.

 

1. 터미널에 npm install multer를 입력해 라이브러리를 다운로드 해준다. 

 

2. 아래와 같이 라이브러리를 세팅해준다.

let multer = require('multer');
var storage = multer.diskStorage({ //diskStorage: 업로드된 파일을 하드에 저장할 수 있게 해주는 함수.

  destination : function(req, file, cb){ //destination: 업로드된 파일을 하드의 어떤 경로에 저장할지 정하는 부분
    cb(null, './public/image')
  },
  filename : function(req, file, cb){ //파일 이름을 저장하는 부분 file.originalname은 그냥 원본 그대로 저장한다는 의미이다.
    cb(null, file.originalname )
  }

});

// 업로드한 파일의 확장자 필터 / 업로드만 하고 싶다면 var upload = multer({storage : storage}); 

var path = require('path');

var upload = multer({
    storage: storage,
    fileFilter: function (req, file, callback) {
        var ext = path.extname(file.originalname);
        if(ext !== '.png' && ext !== '.jpg' && ext !== '.jpeg') {
            return callback(new Error('PNG, JPG만 업로드하세요'))
        }
        callback(null, true)
    },
    limits:{
        fileSize: 1024 * 1024
    }
});

 

3. post 요청을 할때 미들웨어로 upload를 호출해준다.

app.post('/upload', upload.single('profile'), function(request, response){
    response.send('업로드완료')
});

 

여기서 upload만 미들웨어로 작성한게 아니라 upload.single('profile')로 미들웨어를 작성한 이유는?

사진파일 하나만 업로드할 것이기 때문에 single을 사용했고, profile을 작성한 이유는 해당 이름으로된 inpu에서 이미지를 가져올 것이기 때문이다.

 

그렇다면 여러 사진들은 어떻게 업로드하나?

upload.array('profile', 이미지 개수) 로 코드를 작성하면 된다.


4. 업로드한 이미지 보여주기

app.get('/image/:imageName', function (request, response) {
    response.sendFile(__dirname + '/public/image/' + request.params.imageName)
})

 

 

 [ 결과 ]