2014-07-18 13 views
18

Sto lavorando con un'API personalizzata per consentire a un utente di caricare un file (di dimensioni, si spera, arbitrarie). Se il file è di grandi dimensioni, sarà chunkfied e gestito in più richieste al server.Che cosa sta facendo in realtà il metodo File5lice HTML5?

Sto scrivendo il codice che utilizza File e FileReader (HTML5) come per molti esempi da online. In generale (da quello che ho letto on-line) per un trasferimento di file chunkfied, la gente prima ottenere un blob di dati dal proprio oggetto file

var file = $('input[type=file]')[0].files[0]; 
var blob = file.slice(start,end) 

Quindi utilizzare un FileReader di leggere il blob readAsArrayBuffer(blob) o readAsBinaryString(blob)

E infine nel metodo FileReader.onload(e), inviare i dati al server. Ripeti questa procedura per tutti i blocchi nel file.

Le mie domande sono

Perché ho bisogno di usare un FileReader? Se non lo uso, e semplicemente invio di BLOB con File.slice, esiste la garanzia che l'operazione di slicing verrà eseguita prima di provare a inviare i dati in ogni richiesta. L'oggetto File carica l'intero file quando viene creato (sicuramente no?). File.slice cerca la posizione stabilita dai parametri, quindi leggi le informazioni in? La documentazione non mi dà indicazioni su come è stata implementata.

risposta

21

La cosa importante da tenere presente è che File eredita da Blob, File in realtà non ha un metodo slice, ottiene questo metodo da Blob. File aggiunge solo un paio di attributi di metadati.

Il modo migliore per pensare a un Blob (o File) è come un puntatore ai dati, ma non i dati effettivi stessi. Un po 'come un handle di file in altre lingue.

Non è possibile accedere ai dati in un Blob senza utilizzare un lettore, che legge in modo asincrono per evitare di bloccare il thread dell'interfaccia utente.

Il metodo Blob slice() restituisce solo un altro Blob, ma ancora una volta, questo non è dati, è solo un puntatore a un intervallo di dati all'interno del Blob originale, un po 'come un puntatore limitato a una vista. Per ottenere effettivamente i byte dal Blob tagliato, è comunque necessario utilizzare un lettore. Nel caso di un blob a fette, il tuo lettore è limitato.

Questo è veramente solo inteso come una comodità in modo che tu non debba portare una serie di offset relativi e assoluti nel tuo codice, puoi solo ottenere una vista limitata dei dati e usare il lettore come se tu stavo leggendo dal byte 0.

Nel caso di XMLHttpRequest (supponendo che il browser supporti l'interfaccia più recente) i dati verranno trasmessi in streaming su invio e vincolati dai limiti del blob. Fondamentalmente, funzionerà allo stesso modo in cui immagineresti che funzioni se hai inviato un puntatore a un metodo di streaming (che è fondamentalmente quello che sta succedendo sotto le copertine). https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data#Sending_binary_data

In sostanza, è un lettore pigro. Se il blob è già caricato/letto dal file system o è stato creato in memoria, lo userà solo. Tuttavia, quando si utilizza un file, verrà caricato e trasmesso pigramente in modo asincrono dal thread principale.

La logica di base è che gli sviluppatori di browser non desiderano mai che una lettura avvenga in modo sincrono perché potrebbe bloccare il thread principale, quindi tutte le API sono progettate attorno a tale filosofia di base. Nota come Blob.slice() è sincrono - è così che sai che in realtà non sta facendo alcun IO, ma sta solo impostando limiti e (possibilmente) puntatori di file.

+1

Grazie per aver definito File per me, questo ha molto più senso. Tuttavia, se utilizzo ancora File.Slice (che restituisce un blob), quindi proverò a inviare il blob al server utilizzando XMLHttpRequest.send (myBlob), come/quando sono i dati recuperati dal file e dati al server . O questo fallirà/non invierà alcun dato? - – Ponml

+0

Ho aggiornato la mia risposta per dare qualche dettaglio in più. Sono entrato in questa roba molto profondamente quando stavo scrivendo la mia utility rsync javascript: https://github.com/claytongulick/bit-sync –

Problemi correlati