Node.js

[Node.js] 6. 파일 업로드

반응형

우리는 블로그나 카페에서 내가 갖고 있는 파일을 업로드할 수 있다. Node.js에서도 이러한 파일 업로드를 만들어 실습해보자


express에서는 기본적으로 파일 업로드에 대해서 지원해주지 않는다. 따라서 이에 해당하는 모듈을 설치해야한다.


multer라는 모듈은 우리가 파일 업로드를 할 수 있도록 도와준다. npm을 통해서 설치하자


1
2
3
4
5
//설치
npm install multer --save
 
//app_file.js에 작성
var multer = require('multer');
cs


multer 모듈을 사용하기 위해 app_file.js에 위와 같이 require 문을 작성하도록 한다.


우리가 업로드할 파일을 저장할 uploads 폴더를 하나 만들고, multer로 해당 경로를 아래와 같이 app_file.js에 설정해준다.


1
var upload = multer({ dest: 'uploads/' })
cs

views_file 폴더에 upload경로에 보여줄 pug파일을 생성하자

1
2
3
4
5
6
7
8
doctype html
html
  head
    meta(charset='utf-8')
  body
    form(action='upload' method='post' enctype="multipart/form-data")
      input(type='file' name='userfile')
      input(type='submit')
cs

input으로 file 타입과 전송할 submit을 만든다.
전송에 해당하기 때문에 method는 post이다.

enctype은 형식상 작성해야 하는 것이기 때문에 이를 사용할 때 같이 작성해두도록 하자.


이제 app_file.js에 upload경로를 불러올 get과 post를 작성하자


1
2
3
4
5
6
7
app.get('/upload', function(req, res){
    res.render('upload');
})
 
app.post('/upload', function(req, res){
    res.send('Uploaded');
})
cs

upload 경로에 접속하여 파일을 전송하면, Uploaded가 출력되는 것을 확인할 수 있다.

하지만 아직 uploads 폴더에 파일이 저장되는 것은 구현되지 않은 상태다. 지금부터 알아보자


multer 메뉴얼 사이트를 보면, 파일을 전송하는 post를 구현할 때 upload.single을 사용하는 걸 볼 수 있다.
이를 이용해 아래와 같이 post를 작성해주자.

1
2
3
app.post('/upload', upload.single('userfile'), function(req, res){
    res.send('Uploaded : ' + req.file);
});
cs

인자로 upload.single을 추가하고, 현재 upload.pug에서 file 타입의 이름을 userfile이라고 지정했으므로 이를 가져오도록 한다. 이제 파일을 전송했을 때 uploads 폴더에 파일이 추가되는 모습을 볼 수 있다.

하지만 업로드 이 후 결과로 파일의 이름이 제대로 출력되지 않는다. 따라서 req.file.filename으로 수정하고 콘솔을 통해 저장된 파일의 세부정보를 볼 수 있도록 만들자.

1
2
3
4
app.post('/upload', upload.single('userfile'), function(req, res){
    console.log(req.file);
    res.send('Uploaded : ' + req.file.originalname);
});
cs

이제 콘솔에서 나오는 filename의 정보가 화면에 출력이 잘 될 것이다.

하지만 프로젝트 상에서 uploads에 저장되는 파일의 이름은 originalname이 아닌 filename으로 저장돼서 정확한 확인이 불가능하다.

이를 똑같은 originalname으로 주고 싶다면, 아래와 같은 storage 형식을 사용해야 한다.

1
2
3
4
5
6
7
8
9
10
var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, '/tmp/my-uploads')
  },
  filename: function (req, file, cb) {
    cb(null, file.fieldname + '-' + Date.now())
  }
})
 
var upload = multer({ storage: storage })

cs


따라서 맨 마지막의 upload 부분의 multer를 storage로 바꿔주자. 같은 storage면 헷갈릴 수 있기 때문에,

multer({ storage: _storage })로 언더라인을 주고 시작지점의 var 이름도 _storage로 바꿔준다.

destination은 목적지를 나타내므로, 아래 경로를 우리 파일이 저장되는 'uploads/'로 바꿔준다.
filename은 해당 프로젝트 내에 저장되는 데이터의 파일 이름을 나타내므로 file.originalname으로 바꿔서 저장해준다.


저장된 결과는 아래와 같다.

1
2
3
4
5
6
7
8
var _storage = multer.diskStorage({
    destination: function (req, file, cb) {
      cb(null, 'uploads/')
    },
    filename: function (req, file, cb) {
      cb(null, file.originalname)
    }
})
cs


왜 이런 형식을 사용하는 걸까?

왜냐하면 storage를 사용할 때 우리는 콜백 함수를 통해 높은 자유도를 가질 수 있다. 따라서 내가 저장하는 파일의 형식(이미지, 텍스트 등)마다 다른 폴더로 저장하도록 구성하는데 편하다.

// if(파일의 형식이 이미지면)
// cb(null, 'uploads/images');
// else if(텍스트면)
// cb(null, 'uploads/texts')''


이런식으로 if문을 사용해 파일 형식마다 경로 설정도 가능하도록 storage를 통해 만들 수 있다.





반응형