2012-11-09 3 views
9

HTML 폼에서 멀티 파트 POST를 수신하고 들어오는 데이터를 Amazon S3에 파이프하는 작은 node.js 응용 프로그램을 작성하고 있습니다. formidable 모듈은 multipart parsing을 제공하고 각 부분을 노드 Stream으로 나타냅니다. knox 모듈은 PUT을 s3으로 처리합니다.node.js에서 업로드 진행 상황을보고합니다.

var form = new formidable.IncomingForm() 
, s3 = knox.createClient(conf); 

form.onPart = function(part) { 
    var put = s3.putStream(part, filename, headers, handleResponse); 
    put.on('progress', handleProgress); 
}; 

form.parse(req); 

나는 socket.io를 통해 브라우저 클라이언트로 업로드 진행 상황을보고하고있어,하지만 어려움 S3 업로드 할 노드의 실제 진행 상황을 반영하기 위해이 숫자를 얻는 데.

노드 업로드 프로세스가 로컬 네트워크에서 실행될 때처럼 노드 업로드 브라우저가 즉시 거의 발생하면 진행 표시기가 즉시 100 %에 도달합니다. 파일 크기가 300MB 인 경우 진행 표시기는 천천히 상승하지만 여전히 업스트림 대역폭보다 빠릅니다. 100 % 진행을 마친 후 클라이언트는 멈추어 s3 업로드가 끝날 때까지 기다립니다.

stream.pipe 메서드를 내부적으로 사용하는 putStream을 알고 있지만 어떻게 작동하는지 자세히 알지 못합니다. 내 가정은 노드가 들어오는 데이터를 가능한 한 빨리 거꾸로하여 메모리에 던집니다. 쓰기 스트림이 데이터를 충분히 빨리 처리 할 수있는 경우 데이터를 쓰거나 버릴 수 있으므로 작은 데이터가 즉시 메모리에 보관됩니다. 쓰기 스트림이 느린 경우에도 여기에 설명 된대로 모든 들어오는 데이터를 쓸 수있을 때까지 메모리에 보관해야합니다. 진행률을 높이기 위해 읽기 스트림에서 data 이벤트를 수신하므로 업로드가 실제로보다 빠르게 진행되는 것으로보고됩니다.

어디에서나이 문제에 대해 잘 알고 있습니까? 어떻게 고칠 수 있을까요? write, drainpause으로 내려와 더러워 져야합니까?

+0

당신은'handleProgress' 콜백 내에서 브라우저로 진행 상황을보고하고이 같은

무언가가 당신의 문제를 해결해야합니까? 실제 진행보고와 관련이있는 코드를 게시하지 않았습니다. 더 많은 코드를 게시하면 도움이 될 것입니다. – lanzz

+0

사용중인 Node.JS의 버전은 무엇입니까? 'request.pause()'(귀하의 경우 :'part' 변수)와 함께 appletntly [버그가있었습니다] (https://groups.google.com/forum/?fromgroups=#!topic/nodejs/pzhtOO6ePZ0) Node.JS v0.6.x는'.pipe()'에 의해 내부적으로 사용됩니다. 이것은 v0.7 +에서 수정되어야합니다. – freakish

+0

@lanzz - 맞습니다. 실제 구현은 실제로 관련이 없습니다. 질문의 목적을 위해 "console.log"도있을 수 있습니다. – cantlin

답변

7

문제는 stream.pause isn't implemented on the part이며, 이는 멀티 파트 폼 파서의 출력물의 매우 간단한 읽기 스트림입니다.

Knox instructs the s3 request to emit "progress" events whenever the part emits "data". 그러나 part 스트림이 일시 중지를 무시하므로 양식 데이터를 업로드하고 구문 분석 할 때 최대한 빨리 진행 이벤트가 생성됩니다.

그러나 무시 무시한 formpauseresume (구문 분석중인 요청에 대한 호출을 프록시 함) 모두를 알고 있습니다.

form.onPart = function(part) { 

    // once pause is implemented, the part will be able to throttle the speed 
    // of the incoming request 
    part.pause = function() { 
     form.pause(); 
    }; 

    // resume is the counterpart to pause, and will fire after the `put` emits 
    // "drain", letting us know that it's ok to start emitting "data" again 
    part.resume = function() { 
     form.resume(); 
    }; 

    var put = s3.putStream(part, filename, headers, handleResponse); 
    put.on('progress', handleProgress); 
}; 
+0

감사합니다. numbers1311407, 훌륭한 답변입니다. 이런 식으로''멈춤''과''다시 시작하기 '를 구현할 때 중대한 결점을 볼 수 있습니까? 실제로 s3만큼 반응이 좋을 때만 서버를 만들 수 있다고 가정합니다. 테스트 코드 [여기] (https://github.com/cantlin/node-s3-proxy)에서 구현했습니다. – cantlin

+0

나는 나 자신이 입을 다물지 않기 때문에 나는 똑같은 것을하는 경향이있다. 그러나 [node.js 스트림 문서 페이지] (http://nodejs.org/api/http.html#http_request_pause)는 업로드 조절이 '일시 중지'에 대한 유용한 사례라고 언급합니다. [request.pause "버그"에 대한 뉴스 그룹 토론 (https://groups.google.com/forum/#!msg/nodejs/yv6Dl-O-wYk/qPAKqKDDT9gJ)은 유용 할 것입니다 (Mikeal 및 Marco의 의견). – numbers1311407

+0

결국 두 가지 문제가 해결됩니다. 1. 실제 업로드가 완료 될 때까지 클라이언트를 계속 온라인 상태로 유지하고 2. 서버에서 잠재적으로 많은 양의 데이터를 버퍼링하지 않고이 작업을 허용합니다. 또한 s3 요청 전에 버퍼링 된 스트림으로 파이핑하고 거기에서 진행 상황을 모니터링하고 업로드가 끝나면 클라이언트를 다시 호출하여이 문제를 해결할 수 있습니다. 그러나 이것은 # 2를 던졌습니다. – numbers1311407