간단한것 같지만 간단하지 않은것 같습니다.

루트 URL로 접근시에 업로드 할수 있는 웹페이지를 Response 해 줍니다.

웹유저가 업로드 할 파일을 선택하고 제출버튼을 클릭했을때 Node.js 에서 처리해야 합니다.

Http Methos: post, enctype = Multipart/form-data 로 제출형식을 설정합니다.

1. Request객체에 있는 이벤트를 가지고 데이타를 분리해 낼수 있습니다. data, end 이벤트를 사용합니다.

2. formidable 모듈을 사용해서 파일을 저장할수 있습니다.

여기서 접근하기 쉽도록  저장될 폴더를 일단 지정합니다.

formidable.uploadDir = "tmp";

그리고 renameSync 을 해서 최종저장 하면 될듯 한데 아직 해보지는 않았습니다.


Readable Streams

이벤트 : data, end, error, close

메소드 : pause, resume, end, destroy

writable Streams

이벤트 : drain, error, close, pause, resume

메소드 : write, end, destroy


readable.pipe(writable)

Readable streams can be piped to writable streams. and vice verse.

on('data') => write(), on('end') => end(), on('drain') => resume(), on('close') => destroy(), 

on('error') => error(), on('pause') => pause()


filesystem 에서 writeStream 이라는 메소드가 있는데 http 를 통해서 바이너리 데이타가 이동할때 사용해야 할듯 합니다.

readStream 사용하는 방법

writeStream 사용하는 방법


Drag & Drop 을 사용한 파일업로드 자바스크립트 분석

함수표현식으로 4가지가 있습니다.

기명함수 표현식 a = function a(){};

익명함수 표현식 a = function(){};

즉시실행 기명함수 표현식 ( function a(){ } )();

즉시실행 익명함수 표현식 ( function() { } )();

즉시실행 익명함수 표현식으로 함수가 작성되어 있습니다.


Introduction to XMLHttpRequest Level 2


New Tricks in XMLHttpRequest2


XMLHttpRequest 오브젝트 분석

이벤트핸들러(event handler) : 이벤트가 발생했을때 스크립트가 해당 이벤트에 반응하도록 만든 장치

attributetypeExplanation
onloadstartloadstartWhen the request starts.
onprogressprogressWhile loading and sending data.
onabortabortWhen the request has been aborted, either by invoking the abort() method or navigating away from the page.
onerrorerrorWhen the request has failed.
onloadloadWhen the request has successfully completed.
ontimeouttimeoutWhen the author specified timeout has passed before the request could complete.
onloadendloadendWhen the request has completed, regardless of whether or not it was successful.


1. request timeout 을 설정할수 있습니다.

2. FormData Object를 가지고 binary 데이타를 보낼수 있습니다.

FormData Object은 multipart/form-data 인코딩타입으로 보내지고 XHR이 바이너리 데이타를 보낼수 있도록 합니다.

Html form에서 FormData를 사용하기

var submitHandler = function(event) {

  var dataToSend = new FormData(event.target), xhr = new XMLHttpRequest();

  xhr.open('POST','/processing_script');

  xhr.send(dataToSend);

}

var form = document.getElementById('myform');

form.addEventListener('submit',submitHandler,false)


XHR 을 사용하기 위해서는 객체를 생성한 다음에 open 함수를 가지고 전송방식과 url 을 설정하고 send 함수를 호출하면 됩니다. 여기서 비동기방식으로 진행되기 때문에 서버의 응답을 처리하는 로직이 들어갈 필요가 있습니다.

this.readyState == 4 && this.status == 200


다시 돌아와서 업로드 함수에서 XMLHttpRequest 객체를 생성해서 처리하고 있습니다.

FormData 오브젝트를 생성하고 이 오브젝트에 업로드할 파일을 첨부합니다. 오브젝트의 append(name, value) 함수를 사용합니다.

드래그 & 드랍시에 선택된 파일리스트를 목록을 먼저 작성합니다. 이때 사이즈합을 구해둡니다.

각 파일별로 XHR 오브젝트를 사용하여 FormData 에 담아서 Request를 날립니다.

그리고 responseText 를 result 공간에 innerHTML 를 사용하여 결과를 입력합니다.

서버에서 응답하는 responseText 의 형태는 'File uploaded to: ' + target_path + ' - ' + req.files.myfile.size + ' bytes' 이와 같습니다.

Retrieving a FileList Object

The HTML5 FileList object is an array-like collection of File objects. File input fields return a FileList via a files property (event.target.files). Dropped files return a FileList object via the event’s dataTransfer.files property (event.dataTransfer.files).

We can therefore retrieve a FileList object using single event handler:


// cancel event default
e.preventDefault();
// fetch FileList object
var files = e.target.files || e.dataTransfer.files;
// process all File objects
for (var i = 0, file; file = files[i]; i++) {
	...
}


Analyzing File Objects

FileList collections contain a number of File objects. Three useful File properties are provided:

  1. .name: the file name (it does not include path information)
  2. .type: the MIME type, e.g. image/jpeg, text/plain, etc.
  3. .size: the file size in bytes.

It’s possible to check a file type and size before further processing or uploads occur, e.g.


// process image files under 300,000 bytes
if (file.type.indexOf("image") == 0 && file.size < 300000) {
	...
}


특정폴더에 업로드된 파일리스트 내역 보기

filesystem 모듈을 가져와서 readdir 함수를 사용하여 파일목록을 가져오는데 콜백함수를 생성해서 처리합니다.

파일목록에 해서 stat 함수를 사용하여 파일의 속성을 가져옵니다. 물론 처리하는 방법은 콜백함수를 사용합니다.

파일 위치, 파일 명, 파일크기, 파일 수정시간을 객체에 담아서 목록배열객체에 해당객체를 저장합니다.

파일 찾기 기능도 이 프로세스내에서 구현할수 있습니다.

해당 목록배열객체를 response 객체에 담아서 보냅니다.


파일리스트에서 선택된 파일을 다운로드하기

response 객체의 download 함수를 사용하면 됩니다.



블로그 이미지

희망잡이

,



node.js의 영역에 대한 아키텍쳐 그림입니다.

정보를 찾다 보니 여기까지 오게 되었네요.ㅠㅠ 내것으로 만들기엔...

출처) http://www.ibm.com/developerworks/cloud/library/cl-nodejscloud/?cmp=dw&cpb=dwcld&ct=dwnew&cr=dwnen&ccy=zz&csr=042811




위사이트에는 2011년에 Node.js, Html5 에 관한 기초자료가 있습니다.

https://www.ibm.com/developerworks/mydeveloperworks/blogs/0fbe83eb-1b06-4f42-b5f3-45cd0a1dd129/entry/this_week_s_developerworks_newsletter_innovate_2011_node_js_html5_sugarcrm_and_more?lang=en

node, express

http://www.smartjava.org/content/tutorial-nodejs-and-expressjs-part-i-routers




블로그 이미지

희망잡이

,




Application Development with IBM DB2

라는 제목으로 Node.js 를 사용하여 DB2에 접근하는 프레임워크를 제시한 기술문서입니다.

출처 ) https://www.ibm.com/developerworks/mydeveloperworks/blogs/pd/?lang=en


블로그 이미지

희망잡이

,




사람들 대부분 스마트폰을 가지고 다니는 세상에서 스마트폰으로 무엇을 할수 있을까요?
안드로이드 앱시장 또는 애플 앱시장에서 유료, 무료로 필요한 어플을 다운로도해서 설치할수 있습니다.
그리고 직접 앱을 개발할수 도 있겠지요.
앱을 개발하기엔 개발환경이 무겁고 테스트하기에도 쉽지 않은것 같습니다.
그러면 구지 앱을 만들지 않고 웹앱을 만들면 어떨까?
스마트폰 화면에서 아이콘을 클릭하면 바로 웹브라우저가 기동되고 웹을 통해 정보를 주고 받으면 편할것 같은 생각이 드네요.

구축환경은 대충 이렇습니다.
Client
  안드로이드 스마트폰, 애블 아이폰
  
Server
  Node.js
  Html5 로 웹화면 설계
  Jdbc 로 SQL Server 접근

기존 웹서버를 운영한다면 간단하지 않을까 싶습니다.

그래서 Node.js 에서  SQL Server 에 JDBC로 접근할수 있는 방법이 나와 있을까?

=> 추가
node-tds 모듈이 제공되네요.

 일단 MS SQL에서 JDBC Driver를 내놓은 것 같네요.

아직 자세히 들여다 보지는 않았지만 개발흐름의 변화를 감지하게 되는것도 같습니다.

Introducing the Microsoft Driver for Node.JS for SQL Server
출처) http://blogs.msdn.com/b/sqlphp/archive/2012/06/08/introducing-the-microsoft-driver-for-node-js-for-sql-server.aspx


블로그 이미지

희망잡이

,



Node 를 사용하여 Javascript 언어로 어플리케이션을 개발하기위한 기초를 다지기에 좋은 교재가 있습니다.

사이트 : http://www.nodebeginner.org/index-kr.html



구글 크롬 웹브라우저에서 사용하고 있는 V8 Javascript Engine을 사용합니다.

웹어플리케이션의 유스케이스는 아래와 같습니다.

1. 사용자는 웹브라우저로 우리의 웹어플리케이션을 이용할수 있다.

2. 사용자가 http://domain/start 를 요청하면 파일 업로드 폼이 들어있는 웰컴 페이지를 볼수 있어야 한다.

3. 업로드할 이미지 파일을 선택해서 폼으로 전송하면 해당이미지는 http://domain/upload 로 업로드 되어야 하며 업로드가 끝나면 해당페이지에 표시된다.


사용자가 웹브라우저를 통해서 REQUEST를 보내면 서버가 이 REQUEST 를 받아서 작업을 한 다음에 RESPONSE 를 보냅니다.

이 유스케이스를 구현하기 위해 필요한 기술은?

1. 웹페이지를 전송할수 있는 웹서버   => NODE.js 사용

2. REQUEST 내용에 따라 응답을 다르게 하는 방법 => 라우터(ROUTER) 구축

3. 라우팅된 REQUEST 를 처리하기 위한 로직 => 요청 핸들러(request handlers)

4. REQUEST 와 함께 넘어오는 POST 데이타를 분리해서 넘겨주는 기능 => 요청데이타핸들링(request data handling )

5. RESPONSE로 보내기 위한 웹화면 생성 => 뷰로직( view logic )

6. 사용자가 이미지를 업로드 할수 있는 기능 => 업로드 핸들링( upload handling )


main 파일을 작성하는데 파일명은 index.js 로 합니다.

그리고 서버모듈을 가지고 있는 파일명은 server.js 로 합니다.

서버모듈의 프로세스는

구현되어져 있는 http 모듈을 가져와서 http server 를 생성합니다. 포트는 8888 로 설정하는 거지요.

var http = require("http");

http.createServer(function(request, response) {

response.writeHead(200, {"Content-Type": "text/plain"});

response.write("Hello World");

response.end();

}).listen(8888);

서버실행 : node server.js

클라이언트 접속 : http://localhost:8888/


함수의 인자로 함수를 전달하기

event-driven callbacks

: 이벤트에 의해 구동되는 함수가 있고 이 함수에 인자로 넘겨진 호출되어야 할 함수가 있다면 이벤트에 의해 구동되는 함수가 인자로 넘어온 함수를 호출하도록 하는 겁니다.

즉 우리는 메소드에 함수를 넘기고, 메소드는 관련된 이벤트가 발생하면 이 함수를 거꾸로 호출(call back) 합니다.

위의 소스에서 콜백 함수는 function(request, response) 입니다.

var http = require("http");

Node.js 내부 어딘가에 http 라는 모듈이 있으며 이를 require 하고 지역변수에 할당해서 사용할수 있습니다.

이렇게 하면 지역변수가 http모듈이 제공하는 모든 public 메소드를 사용할수 있는 객체가 됩니다.

모듈의 생성과 사용하기

server.js를 모듈로 생성해할수 있습니다.

코드를 모듈로 만든다는 것은 모듈을 필요로 하는 스크립트에 제공할 기능의 일부를 export 하는 것입니다.

우리 서버모듈을 require 하는 스크립트는 단순히 서버를 시작하는것이 필요할 것입니다.

start 하는 기능 즉 함수를 만들고  이 함수를 export.start = start 형식으로 지정하면 됩니다.

내장모듈(http)을 사용하는 것처럼 외장모듈(server.js) 도 똑같이 사용하면 됩니다.

파일을 require 하고 지역변수에 할당하면  export 된 함수를 쓸수 있게 됩니다.

요청을 라우터 하기

웹브라우저의 페이지에서 요청을 보내면 url 과 정보( get방식, post방식)가 함께 전송됩니다.

우리가 필요한 정보 : request 객체를 통해 접근가능, url 모듈querystring 모듈이 필요


url.parse(string).query
                                           |
           url.parse(string).pathname      |
                       |                   |
                       |                   |
                     ------ -------------------
http://localhost:8888/start?foo=bar&hello=world
                                ---       -----
                                 |          |
                                 |          |
              querystring(string)["foo"]    |
                                            |
                         querystring(string)["hello"]

querystring 모듈을 POST 요청의 body를 파싱하는데에도 사용할 수 있습니다.

var pathname = url.parse(request.url).pathname;

여기서 /start, /upload 를 pathname 으로 구분할수 있을것입니다.

router 모듈에서 pathname 을 받아서 처리할수 있도록 합니다.

정리하면 server.js 모듈이 start 할때 router 모듈을 인자로 받아서 실행을 하면서 콜백함수 onRequest에서 router 를 호출하는것으로 흘러갑니다.

동사들의(verbs) 나라에서의 실행(execution)

functional programming 에 대한 이야기 - 무엇인가를 해야 할때 명사보다는 동사의 행동이 필요하다.

실제 request handler 로 라우팅(routing) 하기

라우터를 통해 라우팅된 실제 비지니스로직을 수행하는 requestHandlers 모듈을 만들 필요가 있습니다.

두개의 기능이 모듈에서 export 되어야 합니다.

exports.start = start;

exports.upload = upload;

request handler는 지금은 두개 있지만 실제 어플리케이션에서는 handler의 수가 늘어나고 다양해 질것입니다.

라우터에서 request 와 handler를 매핑하거나 if code 문을 쓰는것은 추악함 이상이 될것입니다.

javascript 의 객체는 키 값이 문자열인 사전(dictionary) 이라고 생각하세요. 이름 값의 컬렉션. 이 값에는 문자일수 도 숫자일수 도 함수일수도 있다는 것입니다.

requestHandler 의 리스트를 객체로 넘기고 느슨한 연결을 위해 이 객체를 router 로 주사하려고 합니다.

index.js 에서 

var handle = {};

handle["/"] = requestHandlers.start;

handle["/start"] = requestHandlers.start;

handle["/upload"] = requestHandlers.upload;

여기서의 handle 을 server 가 시작할때 라우터 와 함께 handle 을 넘겨줍니다.

라우터는 pathname 과 handle 을 인자로 받아서 pathname 에 해당하는 handle 키에 해당하는 값의 함수를 콜백합니다.

if (typeof handle[pathname] === 'function') {

   handle[pathname]();

  } else {

    console.log("No request handler found for " + pathname);

  }

request handler 가 응답하게 만들기

request 처리란 request 에 응답하는 것입니다.

해서는 안되는 것 : 직관적인 접근방식 => 반환값으로 응답데이타를 유저에게 보내는 방식

Blocking 과 non-Blocking

start request handler 에서 10초 동안 기다리도록 수정합니다. ( start time  과 현재 시간을 비교하여 구현 )

/**

function start() {

  console.log("Request handler 'start' was called.");

  function sleep(milliSeconds) {

    var startTime = new Date().getTime();

    while (new Date().getTime() < startTime + milliSeconds);

  }

  sleep(10000);

  return "Hello Start";

}

**/

여기서 10초 동안 sleep 하거나 오랜시간 걸리는 계산작업을 하는 경우에 operation이 blocking 되어 있다고 합니다.

 Node.js는 다수의 동시작업을 처리할 수 있지만 thread를 나누는 방식으로 하지 않습니다. 

 사실 Node.js는 단일 thread입니다. 

 대신, Node.js는 동시작업을 event loop을 실행해서 처리하며 개발자들은 이것을 사용할 수 있습니다. 

 우리는 blocking 동작을 피하고 non-blocking 동작을 사용해야만 합니다.

그러기 위해서는 callback 으로 함수를 다른 함수에게 넘겨야 합니다.

/**

var exec = require("child_process").exec;

function start() {

  console.log("Request handler 'start' was called.");

  var content = "empty";

  exec("ls -lah", function (error, stdout, stderr) {

    content = stdout;

  });

  return content;

}

**/

위 start 함수의 실행결과는 empty 가 바로 출력이 됩니다.

우리는 새로운 Node.js 모듈인 child_process를 사용했습니다. 

매우 단순하지만 쓸모가 많은 non-blocking 동작인 exec()을 사용하기 위해서 입니다.

그렇지만 그 이유는 exec()을 호출하자 마자 Node.js는 이어서 return content;를 실행합니다. 

바로 이 시점에 content는 여전히 "empty" 입니다. 

왜냐하면 exec()은 비동기적으로 동작하기 때문에 exec()에 전달된 callback 함수는 아직 호출되지 않았던 것이죠.


request handler 가 non-blocking 방식으로 동작하면서 응답하기

현재 우리 애플리케이션은 사용자에게 보여주고 싶은 content를 

request handler에서 HTTP server로 전달할 수 있습니다. 

다음과 같은 여러 애플리케이션 레이어들을 거쳐 넘기는 식으로 식으로 말입니다. 

(request handler -> router -> server).


새로운 접근 방법은 다음과 같습니다: 

content를 server로 보내는 대신 server를 content로 보낼겁니다. 

좀 더 자세히 이야기 하면, response 객체 (server의 callback 함수인 onRequest() 에서 얻은)를 

router를 통해 request handler에게 주사(inject) 합니다. 

이제 handler는 이 객체가 가진 함수들을 이용해서 스스로 요청에 응답할 수 있게 되었습니다.


POST 요청 처리하기

textarea 를 하나 제공해서 사용자가 내용을 채우고 submit 해서 post 요청을 서버로 보내는 시나리오 입니다

requestHandler.js 의 start 함수에 testarea를 포함하는 html을 response 하도록 수정합니다.

function start(response) {

  console.log("Request handler 'start' was called.");

  var body = '<html>'+

    '<head>'+

    '<meta http-equiv="Content-Type" content="text/html; '+

    'charset=UTF-8" />'+

    '</head>'+

    '<body>'+

    '<form action="/upload" method="post">'+

    '<textarea name="text" rows="20" cols="60"></textarea>'+

    '<input type="submit" value="Submit text" />'+

    '</form>'+

    '</body>'+

    '</html>';

    response.writeHead(200, {"Content-Type": "text/html"});

    response.write(body);

    response.end();

}

POST 요청은 상당히 클겁니다. 

누구도 사용자가 몇 메가바이트의 텍스트를 입력하는 것을 막을 수 없겠죠. 

전체 데이터 블록을 하나로 처리하는 것은 blocking operation 방법이 될 것입니다.

전체 프로세스를 non-blocking 으로 만들려면, 

POST 데이터를 작은 청크로 나누고 특정 이벤트 때마다 

callback을 호출하는 방식으로 만들어야 합니다.



참고사이트

김종령의 생각 : http://jongryong.wordpress.com/tag/node-js/

screenr.com 웹기반동영상 제작편집 : http://ktk350.blog.me/100144575612

Node.js란? : http://www.ibm.com/developerworks/kr/library/os-nodejs/index.html

CoffeeScript 의 첫경험 : http://www.ibm.com/developerworks/kr/library/os-nodejs/index.html

html5로 flac파일 재생하기 : aurora.js, ofmlabs 의 github

The Node Beginner Book Korean Edition : http://www.nodebeginner.org/index-kr.html


블로그 이미지

희망잡이

,