[ 노드 JS ] 이미지, 업로드 파일 REST API 서버 만들기

많은 모바일 앱 서비스와 웹 서비스는 이미지나 파일들을 업로드하는 기능이 거의 필수적으로 필요합니다. 노드 JS를 통해 REST API 서비스를 만들때 고려해야 하는 부분이죠.

 

이 튜토리얼은 노드 JS와 Express 백엔드 서비스에서 어떻게 복수의 파일을 업로드 하고 저장하는지 알아보겠습니다. 

 

 설치 

 

가장 먼저 아래의 코드를 새로운 노드 프로젝트에 생성합니다. 저는 yarn 패키지 매니저를 사용했지만 npm을 사용해도 상관 없습니다.

 

▼ 1. 폴더 생성 및 이동, upload 라는 폴더를 생성하고 이동합니다.

$ mkdir upload && cd upload

 

▼ 2. yarn, 또는 npm 을 사용해 프로젝트 생성 y 또는 --yes 는 기본값으로 package.json을 생성하고 대화상자를 스킵합니다.

$ yarn init -y 
$ npm init -y

 

▼ 3. 다음으로 필요한 패키지를 설치합니다.

$ yarn add express cors express-fileupload morgan lodash body-parser 
$ npm install express cors express-fileupload morgan lodash body-parser --save

 

  • express - 노드 JS에서 REST API를 만들기 위한 엄청 유명한 웹 생성 프레임워크입니다.
  • cors - CORS (Cross-Origin Resource Sharing) 요청들을 허용하기 위한 또 다른 Express 미들웨어입니다.
  • express-fileupload - 파일 업로드를 위한 간단한 익스프레스 미들웨어 입니다. multipart/form-data 요청을 파싱합니다.
  • morgan - HTTP 요청을 로깅하기 위한 노드 JS 미들웨어입니다.

 

 서버 만들기 

 

필수 설치가 끝나면 이제 간단한 익스프레서 서버를 만들어 보겠습니다. 우선 index.js 라는 파일을 만듭니다.

 

index.js

const express = require('express');
const bodyParser = require('body-parser');
const fileUpload = require('express-fileupload');
const cors = require('cors');
const morgan = require('morgan')
const _ = require('lodash')

const app = express();

// 파일 업로드 허용
app.use(fileUpload({
    createParentPath: true
}));

// 미들 웨어 추가
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(morgan('dev'));

// 포트 설정
const port = 3000;


app.listen(port, () => {
    console.log(`Server is on port ${port}.`);
})

 

처음에 express와 multipart/form-data 요청을 받아들이기 위해 express-fileupload 미들웨어를 추가하고 나중에 Cross-Origin-Resource-Sharing(CORS)를 허용하기 위한 미들웨어를 추가합니다. 로깅을 위한 미들웨어를 설치하고 3000 포트에 웹 서버 응답 객체를 생성합니다.

 

테스트로 실행해 보겠습니다. Server is on port 3000 이라고 뜨면 잘 되는 겁니다.

서버 실행


 

 POST 요청 추가 

app.post('/upload', async (req, res) => {
    try {
        if (!req.files) {
            res.send({
                status: false,
                message: '파일 업로드 실패'
            });
        } else {
            let f = req.files.uploadFile;
            f.mv('./uploads/' + f.name);
            res.send({
                status: true,
                message: '파일이 업로드 되었습니다.',
                data: {
                    name: f.name,
                    minetype: f.minetype,
                    size: f.size
                }
            });
        }
    } catch (err) {
        res.status(500).send(err);
    }
})

이제 간단한 업로드 요청을 만들어보겠습니다. /upload 라는 POST 형태의 API 입니다.  위의 index.js 파일에 포트 설정 위쪽에 작성하면 됩니다. 

 

우선 요청한 객체를 변수에 담습니다.

let f = req.files.uploadFile;

 

파일을 uploads 폴더에 이동시킵니다.

f.mv('./uploads/' + f.name);

 

마지막으로 업로드 되었다는 응답값을 작성합니다.

res.send({
    status: true,
    message: '파일이 업로드 되었습니다.',
    data: {
        name: f.name,
        minetype: f.minetype,
        size: f.size
    }
});

 

 여러 파일 업로드 

 

다음과 같이 코드를 변경하면 loop 를 돌면서 여러 파일을 업로드 할 수 있습니다.

app.post('/upload-multi', async(req, res) => {
    try {
        if (!req.files) {
            res.send({
                status: false,
                message: "파일 업로드 실패"
            })
        } else {
            let data = [];
            
            _.forEach(_.keysIn(req.files.photos), (key) => {
                let photo = req.files.photos[key];

                photo.mv('./uploads/' + photo.name)

                data.push({
                    name: photo.name,
                    minetype: photo.minetype,
                    size: photo.size
                });
            });

            // return response
            res.send({
                status: true,
                message: '파일들이 업로드 되었습니다.',
                data: data
            });
        }
    } catch (err) {
        res.status(500).send(err);
    }
})

 

달라진 것은 루프를 돌면서 저장한다는 것 과 data 라는 변수를 만들어서 push 하고 마지막 응답값을 반환할 때 보내는 것 밖에 없습니다. lodash 유틸을 사용하면 _.forEach() & _.keysIn()) 는 루프를 돌며 업로드 폴더에 사진을 저장합니다.

 

 업로드 테스트 

 

포스트맨에서 간단한 테스트를 해보겠습니다.

www.postman.com/

 

Postman | The Collaboration Platform for API Development

Postman makes API development easy. Our platform offers the tools to simplify each step of the API building process and streamlines collaboration so you can create better APIs faster.

www.postman.com

 

▼ 1. 우선 아무런 이미지를 안넣고 요청을 해보겠습니다. 키 값은 uploadFile 입니다.

1. 업로드 실패


 

▼ 2. 다음은 이미지를 선택하고 요청한 결과입니다. 파일 이름과 크기를 반환합니다.

2. 싱글 파일 업로드


 

▼ 3. 다음은 URL 이 조금 바뀌었죠. upload-multi 라고 변경하고 요처합니다. 이미지는 3개를 추가했구요. 결과는 다음과 같이 배열에 해당 정보가 포함되서 반환됩니다.

3. 여러개의 이미지 업로드


 

 스태틱 사용하기 

 

만약 업로드 파일이 어디서든 접근하고 싶다면 uploads 디렉토리를 스태틱으로 만들어야 합니다.

app.use(express.static('uploads'));

 

이제 이렇게 어디서든 접근이 가능합니다.

http://localhost:3000/icon.png

 

 파일 사이즈 제한 

 

만약 한번에 올릴 수 있는 파일사이즈의 제한을 주고 싶다면 express-fileuploaded 미들웨어의 limits 옵션을 사용합니다.

app.use(fileUpload({
    createParentPath: true,
    limits: {
        fileSize: 2 * 1024 * 1024 * 1024 // 2MB max file(s) size
    },
}));

 

자세한 옵션 확인은 여기서

github.com/richardgirges/express-fileupload

 

richardgirges/express-fileupload

Simple express file upload middleware that wraps around busboy - richardgirges/express-fileupload

github.com

 

'Coding > 노드JS' 카테고리의 다른 글

[ NVM ] 노드.js 기본 (NVM Default) node.js 설정  (0) 2021.02.09

댓글

Designed by JB FACTORY