2012-08-23 146 views
8

我上傳的文件使用Request上傳進度 - 請求

req = request.post url: "http://foo.com", body: fileAsBuffer, (err, res, body) -> 
    console.log "Uploaded!" 

如何知道實際上傳了多少數據?是否有一些我可以訂閱的事件,或者是否有我可以投票的request的屬性?

如果沒有,上傳數據並知道上傳了多少的最佳方法是什麼?

回答

6

我需要處理另一個項目的上傳進度。

我發現的是,你可以輪詢requestconnection._bytesDispatched屬性。

例如:

r = request.post url: "http://foo.com", body: fileAsBuffer 
setInterval (-> console.log "Uploaded: #{r.req.connection._bytesDispatched}"), 250 

注意:如果你正用管道來r,輪詢r.req.connection.socket._bytesDispatched代替。

+0

非常好,謝謝! – darma

+2

也在尋找這個。雖然它看起來像是一個內部API(預計在未來'nodejs'版本中將會發生變化),但它似乎是唯一的解決方案。 –

+2

這是痛苦的;這是唯一可用的Node.js解決方案嗎?嚴重的是,爲什麼Node.js中的文件上傳到HTTP API的問題還沒有解決呢?! – Sukima

-1

有人已經創建了一個很好的模塊來完成這項工作,該模塊已經在transloadit的生產堆棧中運行(所以它可靠且維護良好)。你可以在這裏找到它:

https://github.com/felixge/node-formidable

代碼應該是這樣的:

var formidable = require('formidable'), 
    http = require('http'), 

    util = require('util'); 

http.createServer(function(req, res) { 
    if (req.url == '/upload' && req.method.toLowerCase() == 'post') { 
    // parse a file upload 
    var form = new formidable.IncomingForm(); 
    form.parse(req, function(err, fields, files) { 
     res.writeHead(200, {'content-type': 'text/plain'}); 
     res.write('received upload:\n\n'); 
     res.end(util.inspect({fields: fields, files: files})); 
    }); 
    return; 
    } 

    // show a file upload form 
    res.writeHead(200, {'content-type': 'text/html'}); 
    res.end(
    '<form action="/upload" enctype="multipart/form-data" method="post">'+ 
    '<input type="text" name="title"><br>'+ 
    '<input type="file" name="upload" multiple="multiple"><br>'+ 
    '<input type="submit" value="Upload">'+ 
    '</form>' 
); 
}).listen(80); 

然後,您可以按現狀使用Socket.io

值得注意的一點是客戶端:這是問題之一這導致了Node的創建。在this video Ryan談到節點是如何開始試圖找到通知用戶的最佳方式,實時通過網絡上傳文件的狀態...無論如何我離題了,但如果你有興趣,視頻是值得一看的在Node的歷史中

+1

那麼這是*接收*文件。我*將節點文件發送給另一臺服務器。 –

+4

剛剛花了大約4個小時搜索谷歌。僅僅是我,還是隻有像世界上的**人們從**節點發送文件**到HTTP API?感覺就像共識一樣,Node.js只適用於服務器代碼,對其他任何東西都沒有用處。嘆。 – Sukima

+0

這不僅僅是你..我幾個小時在Google上搜索,仍然沒有找到任何合理的答案..你有什麼發現嗎? – Besat

-1

試試這個辦法:

var file = fs.createWriteStream("largefile.jpg"); 
var totalbytes = request.headers['content-length']; 
var donesofar = 0; 

request.pipe(file); 
request.on('data', function(chunk){ 
    donesofar += chunk.length; 
    var progress = (donesofar/totalbytes) * 100; 
    response.write(parseInt(progress, 10) + "%\n"); 

}); 
3

我花了幾個小時找到任何有效的requestnode來源,終於找到了不同的方法,這感覺更正確的我。

我們可以依靠drain事件和bytesWritten屬性:

request.put({ 
    url: 'https://example.org/api/upload', 
    body: fs.createReadStream(path) 
}).on('drain',() => { 
    console.log(req.req.connection.bytesWritten); 
}); 

另外,如果你需要處理的文件的字節進步,它更容易使用流data事件:

let size = fs.lstatSync(path).size; 
let bytes = 0; 

request.put({ 
    url: 'https://example.org/api/upload', 
    body: fs.createReadStream(path).on('data', (chunk) => { 
    console.log(bytes += chunk.length, size); 
    }) 
}); 

流緩衝區大小是65536字節並且讀/排程序迭代運行。

這對我來說似乎很好,node v4.5.0request v2.74.0

+1

排水方法爲我工作。然而,我不得不通過管道傳輸文件,而不是通過body參數傳遞它。當我通過body參數傳遞它時,它會多次耗盡,但它會快速連續執行,而不是在服務器實際接收數據時執行。看起來,通過身體傳遞它導致它被緩衝,這並沒有給出正確的體驗。乾杯。 – McP

0
var request = require('request'); 
    var fs = require('fs'); 
    let path ="C:/path/to/file"; 
    var formData = { 
     vyapardb: fs.createReadStream(path) 
    }; 

    let size = fs.lstatSync(path).size; 

    var headers = { 
     'Accept' : 'application/json', 
     'Authorization' : 'Bearer '+token, 
    }; 

    var r = request.post({url:'http://35.12.13/file/upload', formData: formData, headers: headers}, function optionalCallback(err, httpResponse, body) { 
     clearInterval(q); 

    }); 
    var q = setInterval(function() { 
     var dispatched = r.req.connection._bytesDispatched; 
     let percent = dispatched*100/size; 
     console.dir("Uploaded: " + percent + "%"); 

    }, 250); 
}