2012-11-09 34 views
9

Tôi đang viết một ứng dụng node.js nhỏ nhận được POST nhiều từ một biểu mẫu HTML và đưa dữ liệu đến Amazon S3. Mô-đun formidable cung cấp multipart parsing, hiển thị từng phần dưới dạng nút Stream. Mô-đun knox xử lý PUT thành s3.Báo cáo tiến trình tải lên từ 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); 

Tôi đang báo cáo tiến độ upload cho khách hàng duyệt qua socket.io, nhưng đang gặp khó khăn khi những con số này để phản ánh sự tiến bộ thực sự của nút để upload s3.

Khi trình duyệt tải lên nút xảy ra gần như ngay lập tức, như khi quá trình nút đang chạy trên mạng cục bộ, chỉ báo tiến trình đạt 100% ngay lập tức. Nếu tệp lớn, tức là 300MB, chỉ báo tiến trình tăng chậm, nhưng vẫn nhanh hơn băng thông ngược dòng của chúng tôi sẽ cho phép. Sau khi đạt được tiến độ 100%, khách hàng sẽ bị treo, có lẽ chờ đợi quá trình tải lên s3 kết thúc.

Tôi biết putStream sử dụng phương pháp stream.pipe của Node trong nội bộ, nhưng tôi không hiểu chi tiết về cách thức thực sự hoạt động. Giả định của tôi là nút gobbles lên các dữ liệu đến nhanh như nó có thể, ném nó vào bộ nhớ. Nếu dòng ghi có thể lấy dữ liệu đủ nhanh, ít dữ liệu được lưu trong bộ nhớ cùng một lúc, vì nó có thể được ghi và loại bỏ. Nếu dòng ghi là chậm mặc dù, vì nó là ở đây, có lẽ chúng ta phải giữ tất cả các dữ liệu đến trong bộ nhớ cho đến khi nó có thể được viết. Vì chúng tôi đang nghe các sự kiện data trên luồng đọc để phát ra tiến trình, chúng tôi sẽ báo cáo việc tải lên nhanh hơn thực tế.

Sự hiểu biết của tôi về vấn đề này ở bất cứ đâu gần điểm đánh dấu? Làm thế nào tôi có thể đi về sửa chữa nó? Tôi có cần phải xuống và bẩn với write, drainpause?

+0

bạn đang báo cáo tiến độ lại cho trình duyệt bên trong 'handleProgress' gọi lại? Bạn chưa đăng _any_ mã có thể có liên quan đến báo cáo tiến độ thực tế. Đăng thêm mã có thể giúp ích. – lanzz

+0

Phiên bản nào của Node.JS bạn đang sử dụng? Apperently [có một lỗi] (https://groups.google.com/forum/?fromgroups=#!topic/nodejs/pzhtOO6ePZ0) với 'request.pause()' (trong trường hợp của bạn: 'part' variable) trong Node.JS v0.6.x, được sử dụng trong nội bộ bởi '.pipe()'. Điều này sẽ được sửa trong v0.7 +. – freakish

+0

@lanzz - Đúng vậy. Việc thực hiện thực tế không thực sự có liên quan mặc dù: cho các mục đích của câu hỏi nó cũng có thể là '' console.log''. – cantlin

Trả lời

7

Vấn đề của bạn là stream.pause isn't implemented on the part, đây là một luồng rất đơn giản của đầu ra từ trình phân tích cú pháp biểu mẫu nhiều phần.

Knox instructs the s3 request to emit "progress" events whenever the part emits "data". Tuy nhiên, do luồng part bỏ qua tạm dừng, các sự kiện tiến trình được phát ra nhanh như dữ liệu biểu mẫu được tải lên và phân tích cú pháp.

Các đáng gờm form, tuy nhiên, không biết làm thế nào để cả hai pauseresume (nó ủy nhiệm các cuộc gọi đến các yêu cầu nó phân tích).

Something như thế này nên khắc phục vấn đề của bạn:

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

Cảm ơn @ numbers1311407, câu trả lời tuyệt vời. Tôi buộc phải hỏi: bạn có thể thấy bất kỳ hạn chế đáng kể nào khi triển khai '' pause'' và '' resume'' theo cách này không? Trong thực tế, tôi cho rằng nó làm cho máy chủ của chúng tôi nhiều nhất chỉ đáp ứng như s3. Tôi đã thực hiện nó trong mã thử nghiệm [ở đây] (https://github.com/cantlin/node-s3-proxy). – cantlin

+0

Vì tôi không có I/O, tôi có xu hướng tự hỏi điều tương tự. Nhưng [trang tài liệu luồng [node.js] (http://nodejs.org/api/http.html#http_request_pause) không đề cập đến việc điều chỉnh tải lên như một trường hợp hữu ích cho 'tạm dừng'. [Thảo luận nhóm tin này về request.pause "bug"] (https://groups.google.com/forum/#!msg/nodejs/yv6Dl-O-wYk/qPAKqKDDT9gJ) đáng xem xét (ý kiến ​​của Mikeal và Marco). – numbers1311407

+0

Cuối cùng nó giải quyết hai vấn đề cho bạn: 1.) nó giữ cho khách hàng trên đường cho đến khi tải lên thực tế đã hoàn thành, và 2.) nó cho phép điều này xảy ra mà không đệm một lượng lớn dữ liệu trên máy chủ. Bạn có thể giải quyết cũng giải quyết vấn đề này bằng cách đường ống tới luồng đệm trước yêu cầu s3, theo dõi tiến độ ở đó và gọi lại máy khách khi quá trình tải lên kết thúc. Nhưng điều này ném ra # 2. – numbers1311407

Các vấn đề liên quan