Node AWS S3 업로드

Posted by Yun on 2017-02-08

Node.Js에서 AWS S3업로드 예제입니다. 본 예제의 전체 소스는 GitHub에서 참고할 수 있습니다.
S3에 관련된 설정이 완료됐다는 가정하에 포스팅을 진행하겠습니다.

필수 패키지 설치

1
2
3
npm install formidable --save
npm install async --save
npm install aws-sdk --save
  • formidable 파일 업로드를 위한 모듈
  • async순차 실행을 위한 모듈
  • aws-sdk S3 업로드를 위한 모듈

HTML Form

1
2
3
4
<form  action="/api/v1/upload" enctype="multipart/form-data"  method="post">
<input type="file" name="img_files[]" accept="image/*">
<button type="submit">Submit</button>
</form>

HTML 입력폼 소스입니다. 간단함으로 넘어가겠습니다.

upload API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Upload = require('../service/UploadService'),
router.post('/upload', function (req, res) {
var tasks = [
function (callback) {
Upload.formidable(req, function (err, files, field) {
callback(err, files);
})
},
function (files, callback) {
Upload.s3(files, function (err, result) {
callback(err, files);
});
}
];
async.waterfall(tasks, function (err, result) {
if(!err){
res.json({success:true, msg:'업로드 성공'})
}else{
res.json({success:false, msg:'실패', err:err})
}
});
});

해당 upload 라우터로 요청이 들어오면 tasks[…]의 작업들이 async
모듈로 순차적으로 실행 됩니다. tasks[…] 작업순서는 다음과 같습니다.

  1. formidable 모듈를 이용해서 Node 서버로 파일을 업로드 시킵니다.
  2. aws-sdk 모듈를 이용해서 AWS S3로 파일을 업로드 시킵니다.
  3. tasks[…] 작업의 결과를 JSON타입으로 클라이언트에게 응답합니다.

세부적인 작업은 UploadService.js에서 callback으로 진행됩니다.
아래에서 설명을 계속 진행하겠습니다.

UploadService.js S3 & formidable설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var
formidable = require('formidable'),
AWS = require('aws-sdk'),
Upload = {};
AWS.config.region = 'ap-northeast-2'; //지역 서울 설정
var s3 = new AWS.S3();
var form = new formidable.IncomingForm({
encoding: 'utf-8',
multiples: true,
keepExtensions: false //확장자 제거
});
/*S3 버킷 설정*/
var params = {
Bucket: 'BucketName',
Key: null,
ACL: 'public-read',
Body: null
};

aws_access_key_id, aws_secret_access_key값을 소스코드에 입력하시는 것은 보안상 바람직하지 않습니다.
AWS Document를 참고하세요.

var params = {…} 객체는 AWS S3업로드에 대한 정보 입니다.

  • Bucket : S3 Bucket 이름을 지정합니다.
  • Key : S3의 경로 및 파일 이름을 지정합니다.
  • ACL : 파일 권한에 대한 설정입니다.
  • Body : 업로드할 파일의 경로를 지정합니다.

UploadService.js 업로드 로직

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Upload.formidable = function (req, callback) {
form.parse(req, function (err, fields, files) {
});
form.on('error', function (err) {
callback(err, null);
});
form.on('end', function () {
callback(null, this.openedFiles);
});
form.on('aborted', function () {
callback('form.on(aborted)', null);
});
};
Upload.s3 = function (files, callback) {
params.Key = 'test/'+files[0].name;
params.Body = require('fs').createReadStream(files[0].path);
s3.upload(params, function (err, result) {
callback(err, result);
});
};
module.exports = Upload;

가장 핵심인 업로드 로직입니다. formidable, s3 메서드는 callback 메서드로
각작업의 결과를 넘겨줍니다.

formidable 메서드 설명
라우터에서 넘겨준 req 객체를 기반으로 파일 업로드를 진행합니다.
파일 업로드 중 에러가 발생하게 되면 form.on(‘error’, …) 메서드를 통해서 에러를 callback으로 넘겨줍니다.

파일 업로드가 정상적으로 완료되면 form.end(null, …)메서드가 호출되고 업로드한 파일의 정보(파일 사이즈, 파일 이름, 파일 경로 등등)가 callback 메서드를 통해서 으로 넘어가게 됩니다.

s3 메서드 설명

async.waterfall를 통해서 넘겨받은 files 객체에는 위에서 설명한 파일 정보가 들어있는 객체입니다.

  • params.Body값에는 위에서 업로드한 파일을 넘겨줍니다.
  • params.Key값에는 실제 S3에 업로드될 path + 파일 이름을 작성합니다.

실행 화면


params.Key 값은 test/[filename] 입니다.
test/는 경로로 인식되며 해당 경로가 없는 경우에는 디렉터리를 자동으로 생성해서 파일을 목적지까지 안전하게? 전달됩니다.

마무리

회사에서 AWS S3업로드를 리펙토링 작업이 있어서 간단하게 정리해봤습니다.
추가로 작업한 부분도 포스팅할 예정입니다.
아무래도 AWS S3 이미지 업로드시 이미지를 최적화시키는 것이 될듯합니다.
앞으로 계속 찾아뵙겠습니다.
RSS 링크도 하단에 추가하였으니 추가해주시면 감사하겠습니다.