파일을 서버의 폴더로 업로드하기
브라우저에서 파일 올리기 요청을 하면 서버에 설정해둔 경로로 파일을 업로드한다
이때 파일 업로드를 위해 사용되는 주 모듈은
1 2 3 | var multer = require('multer'); //파일 업로드하기 위한 모듈 var fs = require('fs'); //파일 시스템 var cors = require('cors'); //다중 서버로 접속하게 해주는 기능을 제공, 다른 ip 로 다른서버에 접속 | cs |
이렇게 3개이다
아래 지정한 경로대로 서버에 업로드할 파일을 전송하게 된다
photo.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>upload file</title> </head> <h1>upload file</h1> <form method="post" action="/process/photo" enctype="multipart/form-data"> <table> <tr> <td><label>file</label></td> <td><input type="file" name="photo" /></td> <!--photo 이 이름이 서버쪽으로 요청파라미터 이름으로 들어가게됨--> </tr> </table> <input type="submit" value="upload" name="summit" /> </form> <body> </body> </html> |
photo.html 실행시킨 모습
서버 nodejs 코드
서버코드인데 중간에 cors 를 사용한 부분이 있는데 이것은 웹페이지를 연서버가 있으면 그 서버로만 접속하게끔 되어 있는 보안 정책이 있는데
파일 업로드하기 위해선 이것을 꼭 서버에만 접속해선 기능을 만들기 힘들수 있음으로 cors 를 상용해 이 정책을 우회한다
var cors = require('cors'); //다중 서버로 접속하게 해주는 기능을 제공, 다른 ip 로 다른서버에 접속
app.use(cors()); //다중 접속을 위한 미들웨에
파일이 저장될 경로 세팅
1 | app.use('/uploads',serveStatic(path.join(__dirname, 'uploads'))); |
웹은 기본적으로 '동일출저정책(Same Origin Policy, SOP)' 정책을 따른다.
이는 보안을 위한 기본정책으로, SOP는 하나의 출처(Origin)에서 로드된 문서나 스크립트가 다른 출처에 존재하는 리소스와 상호작용하지 못하도록 제약을 두는 것이다.
그런데, 간혹 이런 제약이 웹 응용프로그램을 만드는데 걸림돌이 되기도 한다.
Ajax 통신이 활발해 지고, 다른 사이트에 존재하는 Open API와 상호통신이 필요한 경우와 매쉬업(Mash-up)으로 새로운 2차 응용물을 개발하게 되면서.. 등등.. 이는 간혹 걸림돌이 된다.
근래 Node.JS로 서버를 만들고, Aptana Studio 자체 내장 웹서버로 몇 가지 테스트를 하고 있는데, 두 환경은 서로 다른 별도의 포트(Port)에서 웹을 동작시키기 때문에 여지없이 Cross Domain 문제가 발생한다.
호출하는 모든 웹 리소스를, Node.JS로부터 다운로드 받아서 실행하는 구조로 HTTP 서버를 구현하면 SOP 정책을 따를 수 있겠으나, 그렇지 못한 개발환경도 있을 터이고, 실제 서비스 환경에서는 더욱이 서로 다른 도메인(포트 포함)간 상호작용이 필요할 것이다.
SOP 정책을 우회하기 위해서는, 서버 측의 설정이 필요한데, 위 그림에서 친철히 안내하고 있는 것처럼 Access-Control-Allow-Origin 헤더, 즉 크로스 도메인으로 허용할 도메인 목록이 헤더로 제공되어야 한다.
이것을 CORS(Cross-Origin Resource Sharing)를 이용한 SOP 정책 우회라 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | var express = require('express'); var http = require('http'); var serveStatic = require('serve-static'); //특정 폴더의 파일들을 특정 패스로 접근할 수 있도록 열어주는 역할 var path = require('path'); var cookieParser = require('cookie-parser'); var expressSession = require('express-session'); var multer = require('multer'); //파일 업로드하기 위한 모듈 var fs = require('fs'); //파일 시스템 var cors = require('cors'); //다중 서버로 접속하게 해주는 기능을 제공, 다른 ip 로 다른서버에 접속 var app = express(); //express 서버 객체 app.set('port', 3000); app.use(serveStatic(path.join(__dirname, 'public'))); app.use('/uploads',serveStatic(path.join(__dirname, 'uploads'))); var bodyParser_post = require('body-parser'); //post 방식 파서 //post 방식 일경우 begin //post 의 방식은 url 에 추가하는 방식이 아니고 body 라는 곳에 추가하여 전송하는 방식 app.use(bodyParser_post.urlencoded({ extended: false })); // post 방식 세팅 app.use(bodyParser_post.json()); // json 사용 하는 경우의 세팅 //post 방식 일경우 end //쿠키와 세션을 미들웨어로 등록한다 app.use(cookieParser()); //세션 환경 세팅 //세션은 서버쪽에 저장하는 것을 말하는데, 파일로 저장 할 수도 있고 레디스라고 하는 메모리DB등 다양한 저장소에 저장 할 수가 있는데 app.use(expressSession({ secret: 'my key', //이때의 옵션은 세션에 세이브 정보를 저장할때 할때 파일을 만들꺼냐 , 아니면 미리 만들어 놓을꺼냐 등에 대한 옵션들임 resave: true, saveUninitialized: true })); //파일을 올리기위한 세팅 시작 //다중 접속을 위한 미들웨에 app.use(cors()); //파일 업로드를 위한 설정 var fileStorage = multer.diskStorage( { destination: function (req,file, callback) { callback(null, 'uploads'); //목적지 폴더 지정 : 'uploads' 를 목적지로 정한다(이쪽으로 파일이 오게됨) }, filename: function (req, file, callback) { //올린 파일명이 기존과 같으면 덮어씌워짐으로 시간을 기준으로 다른 파일로 저장되게끔 처리한다 var extention = path.extname(file.originalname); var basename = path.basename(file.originalname, extention); //확장자 .jpg 만 빠진 파일명을 얻어온다 var fname = basename + Date.now() + extention; callback(null, fname); } } ); var upload = multer( { storage: fileStorage, limits: { files: 10, //10개까지 fileSize: 1024 * 1024 * 1024 //한번 업로드 할때 최대 사이즈 } } ); //파일을 올리기위한 세팅 끝 //이제 이것을 갖고 라우터를 통해서 파일을 업로드 할수 있게끔 해야함 //라우트를 미들웨어에 등록하기 전에 라우터에 설정할 경로와 함수를 등록한다 // //라우터를 사용 (특정 경로로 들어오는 요청에 대하여 함수를 수행 시킬 수가 있는 기능을 express 가 제공해 주는것) var router = express.Router(); //upload.array : Accept an array of files, all with the name fieldName. //Optionally error out if more than maxCount files are uploaded. //The array of files will be stored in req.files. //('photo',1) : photo 라고 지정한 파일이 있다면 1개를 전송하라는 의미 router.route('/process/photo').post(upload.array('photo',1), function (req, res) { console.log('/process/photo 함수가 호출됨'); var files = req.files; if (files.length > 0) { console.dir(files[0]); } else { console.log('파일이 없음'); } res.writeHead(200, { "Content-Type": "text/html;characterset=utf8" }); res.write('<h1>file upload complete</h1>'); if (Array.isArray(files)) { files.forEach( function (elem) { res.write('<h1>' + elem.originalname + '</h1>'); res.write('<h1>' + elem.filename + '</h1>'); res.write('<h1>' + elem.mimetype + '</h1>'); res.end(); } ); } } ); //http://localhost:3000/process/product 이 주소로 치면 라우터를 통해 바로 여기로 올 수 있다 router.route('/process/product').get( function (req, res) { console.log('/process/product 라우팅 함수 실행'); //세션정보는 req.session 에 들어 있다 if (req.session.user) //세션에 유저가 있다면 { res.redirect('/product.html'); } else { res.redirect('/login2.html'); } } ); router.route('/process/login').post( //설정된 쿠키정보를 본다 function (req, res) { console.log('/process/login 라우팅 함수호출 됨'); var paramID = req.body.id || req.query.id; var pw = req.body.passwords || req.query.passwords; if (req.session.user) { console.log('이미 로그인 되어 있음'); res.writeHead(200, { "Content-Type": "text/html;characterset=utf8" }); res.write('<h1>already Login</h1>'); res.write('[ID] : ' + paramID + ' [PW] : ' + pw); res.write('<a href="/process/product">Move</a>'); res.end(); } else { req.session.user = { id: paramID, pw: pw, name: 'UsersNames!!!!!', authorized: true }; res.writeHead(200, { "Content-Type": "text/html;characterset=utf8" }); res.write('<h1>Login Success</h1>'); res.write('[ID] : ' + paramID + ' [PW] : ' + pw); res.write('<a href="/process/product">Move</a>'); res.end(); } } ); router.route('/process/logout').get( //설정된 쿠키정보를 본다 function (req, res) { console.log('/process/loginout 라우팅 함수호출 됨'); if (req.session.user) { console.log('로그아웃 처리'); req.session.destroy( function (err) { if (err) { console.log('세션 삭제시 에러'); return; } console.log('세션 삭제 성공'); //파일 지정시 제일 앞에 / 를 붙여야 root 즉 public 안에서부터 찾게 된다 res.redirect('/Login2.html'); } ); //세션정보 삭제 } else { console.log('로긴 안되어 있음'); res.redirect('/Login2.html'); } } ); //라우터 미들웨어 등록하는 구간에서는 라우터를 모두 등록한 이후에 다른 것을 세팅한다 //그렇지 않으면 순서상 라우터 이외에 다른것이 먼저 실행될 수 있다 app.use('/', router); //라우트 미들웨어를 등록한다 app.all('*', function (req, res) { res.status(404).send('<h1> 요청 페이지 없음 </h1>'); } ); //웹서버를 app 기반으로 생성 var appServer = http.createServer(app); appServer.listen(app.get('port'), function () { console.log('express 웹서버 실행' + app.get('port')); } ); |
파일을 올리고 나면 다음처럼 파일이 uploads 폴더에 저장되어 있는 것을 확인할 수 있다
정책 일부 ref : http://m.mkexdev.net/339
'서버(Server) > Server&Nodejs&DB' 카테고리의 다른 글
nodejs : mongoDB 를 활용하여 로그인 처리하기 (0) | 2018.05.06 |
---|---|
MongoDB 설치, 데이터베이스서버 MongoDB 간단한 데이터 입력 테스트 (0) | 2018.05.04 |
Nodejs : Express , 세션(session)으로 로그인/아웃 처리 (1) | 2018.05.03 |
Nodejs : Express 쿠키 & 라우터 (0) | 2018.05.02 |
Nodejs , Express : URL 요청파라미터와 등록되지 않은 Path일 경우 예외처리 (0) | 2018.05.02 |