2012-08-23 13 views
8

Sto caricando un file utilizzando Request.Avanzamento caricamento - Richiesta

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

Come faccio a sapere quanti dati sono stati effettivamente caricati? C'è qualche evento a cui posso iscrivermi o c'è una proprietà dello request che posso sondare?

Se nessuno, quale sarebbe l'approccio migliore per caricare i dati e sapere quanto è stato caricato?

risposta

6

Avevo bisogno di gestire l'avanzamento del caricamento per un altro mio progetto.

Quello che ho scoperto è che è possibile interrogare la proprietà connection._bytesDispatched.

Ad esempio:

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

Nota: Se tu fossi tubazioni per r, il polling r.req.connection.socket._bytesDispatched invece.

+0

Molto bello, grazie! – darma

+2

Cerchi anche questo. Sebbene sembri un'API interna (che dovrebbe cambiare nelle future versioni di 'nodejs'), sembra essere l'unica soluzione. –

+2

Questo è doloroso; è questa l'unica soluzione Node.js disponibile? Seriamente, perché non è stato ancora risolto il problema dei caricamenti di file su un'API HTTP in Node.js ?! – Sukima

-1

Qualcuno ha creato un modulo valido per eseguire ciò che è stato eseguito nello stack di produzione per transloadit (quindi è affidabile e ben gestito). Lo si può trovare qui:

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

codice dovrebbe essere simile:

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); 

Si potrebbe quindi spingere lo stato a un client utilizzando Socket.io

Interessante Nota: Questo è stato uno dei problemi questo ha portato alla creazione di Node. In this video Ryan parla di come il nodo è stato avviato cercando di trovare il modo migliore di notificare un utente, in tempo reale, sullo stato del caricamento del file sul web ... comunque sto divagando, ma il video vale la pena guardare se sei interessato nella storia di Node

+1

Beh, questo è per * ricevere * un file.Sto * inviando * un file per il nodo ad un altro server. –

+4

Ho appena trascorso circa 4 ore alla ricerca su Google. Sono solo io o ci sono solo * cinque * persone nel mondo che inviano file ** da ** nodo a un'API HTTP? Sembra che il consenso sia che Node.js è valido solo per il codice server e inutile per qualsiasi altra cosa. Sospiro. – Sukima

+0

Non è solo per te .. Sto cercando su Google per ore e ancora non ho trovato una risposta ragionevole .. hai trovato qualcosa? – Besat

-1

Prova questo approccio:

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

Ho trascorso un paio di ore per trovare qualcosa di valido in request e node fonti, e finalmente trovato un approccio diverso, che si sente più corretto per me.

Possiamo contare su drain evento e bytesWritten proprietà:

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

In alternativa, se avete bisogno di gestire il progresso di byte dei file, è più facile da usare flusso data evento:

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); 
    }) 
}); 

flusso dimensione del buffer è 65536 byte e la procedura di lettura/scarico viene eseguita in modo iterativo.

Questo sembra funzionare abbastanza bene per me con node v4.5.0 e request v2.74.0.

+1

Il metodo di scarico ha funzionato per me. Tuttavia dovevo pipe il file invece di passarlo attraverso il parametro body. Quando l'ho passato attraverso il parametro body, si scaricherebbe più volte, ma lo farebbe in rapida successione e non quando il server ha effettivamente ricevuto i dati. Sembra che passarlo attraverso il corpo ne risulti il ​​buffer, che non fornisce l'esperienza corretta. Saluti. – 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); 
} 
Problemi correlati