Lettura del contenuto dei file sul lato client in javascript in vari browser


113

Sto tentando di fornire una soluzione solo script per leggere il contenuto di un file su una macchina client tramite un browser.

Ho una soluzione che funziona con Firefox e Internet Explorer. Non è carino, ma al momento sto solo provando:

function getFileContents() {
    var fileForUpload = document.forms[0].fileForUpload;
    var fileName = fileForUpload.value;

    if (fileForUpload.files) {
        var fileContents = fileForUpload.files.item(0).getAsBinary();
        document.forms[0].fileContents.innerHTML = fileContents;
    } else {
        // try the IE method
        var fileContents = ieReadFile(fileName);
        document.forms[0].fileContents.innerHTML = fileContents;
    }
}       

function ieReadFile(filename) 
{
    try
    {
        var fso  = new ActiveXObject("Scripting.FileSystemObject"); 
        var fh = fso.OpenTextFile(filename, 1); 
        var contents = fh.ReadAll(); 
        fh.Close();
        return contents;
    }
    catch (Exception)
    {
        return "Cannot open file :(";
    }
}

Posso chiamare getFileContents()e scriverà il contenuto nell'area di fileContentstesto.

C'è un modo per farlo in altri browser?

Al momento sono più interessato a Safari e Chrome, ma sono aperto a suggerimenti per qualsiasi altro browser.

Modifica: in risposta alla domanda "Perché vuoi farlo?":

Fondamentalmente, voglio sottoporre ad hashing il contenuto del file insieme a una password monouso sul lato client in modo da poter inviare queste informazioni come verifica.


non che io abbia una risposta ma solo per chiarezza hai bisogno di conoscere la posizione del file? In caso contrario, la posizione del file deve essere letta da un input di file o può essere una casella di testo / textarea / qualunque cosa?
Darko Z

Buona domanda. No, non mi interessa molto da dove proviene il file, solo il suo contenuto. L'utilizzo di un file di input mi sembra sensato, dato che è html nativo: c'è una cosa in meno che devo fare.
Damovisa

perché vuoi farlo? il server è destinato a farlo.
geowa4

Ok, in breve: un utente inserisce una password e seleziona un file. La password viene sottoposta ad hashing con il contenuto del file e questa viene inviata al server insieme al file. Quando arriva lì, posso verificare che sia stata utilizzata la password client corretta.
Damovisa

Risposte:


159

Modificato per aggiungere informazioni sulla File API

Da quando ho scritto originariamente questa risposta, File API è stata proposta come standard e implementata nella maggior parte dei browser (a partire da IE 10, che ha aggiunto il supporto per le FileReaderAPI descritte qui, sebbene non ancora l' FileAPI). L'API è un po 'più complicata della vecchia API Mozilla, poiché è progettata per supportare la lettura asincrona dei file, un migliore supporto per i file binari e la decodifica di diverse codifiche di testo. C'è della documentazione disponibile su Mozilla Developer Network così come vari esempi in linea. Lo useresti come segue:

var file = document.getElementById("fileForUpload").files[0];
if (file) {
    var reader = new FileReader();
    reader.readAsText(file, "UTF-8");
    reader.onload = function (evt) {
        document.getElementById("fileContents").innerHTML = evt.target.result;
    }
    reader.onerror = function (evt) {
        document.getElementById("fileContents").innerHTML = "error reading file";
    }
}

Risposta originale

Non sembra esserci un modo per farlo in WebKit (quindi, Safari e Chrome). Le uniche chiavi di cui dispone un oggetto File sono fileNamee fileSize. Secondo il messaggio di commit per il supporto File e FileList, questi sono ispirati dall'oggetto File di Mozilla , ma sembrano supportare solo un sottoinsieme delle funzionalità.

Se desideri cambiare questa impostazione, puoi sempre inviare una patch al progetto WebKit. Un'altra possibilità sarebbe quella di proporre l'API di Mozilla per l'inclusione in HTML 5 ; la mailing list WHATWG è probabilmente il posto migliore per farlo. Se lo fai, è molto più probabile che ci sarà un modo cross-browser per farlo, almeno tra un paio di anni. Ovviamente, inviare una patch o una proposta per l'inclusione in HTML 5 significa lavorare per difendere l'idea, ma il fatto che Firefox lo implementa già ti dà qualcosa con cui iniziare.


Grazie per questo - non penso di essermi dedicato abbastanza a questo punto per inviare una patch. È qualcosa che probabilmente non vorresti che accadesse a tua insaputa comunque. Un po 'rompe la sandbox del browser ...
Damovisa

4
Non interrompe la sandbox del browser, poiché hai scelto deliberatamente di caricare quel file; se può arrivare al server, può tornare al browser, solo con un viaggio di andata e ritorno in più. Dato il lavoro che sta facendo per far funzionare la modalità offline per le app Web, questa sarebbe una funzionalità ragionevole.
Brian Campbell,

Mm, in realtà questo è un punto giusto. C'è stata l'interazione dell'utente per scegliere quel file. Grazie.
Damovisa

@Damovisa Non so se ti interessa ancora, ma ho pensato che avrei aggiornato la mia risposta per menzionare la nuova API File che fa quello che stai cercando ed è implementata in Firefox, Chrome e versioni notturne di Safari.
Brian Campbell

Fantastico, grazie per quello. Sono passato ad altri lavori, ma è bello sapere che la risposta c'è :)
Damovisa

25

Per leggere un file scelto dall'utente, utilizzando una finestra di dialogo di apertura file, è possibile utilizzare il <input type="file">tag. È possibile trovare informazioni su di esso da MSDN . Quando viene scelto il file, è possibile utilizzare l' API FileReader per leggere il contenuto.

function onFileLoad(elementId, event) {
    document.getElementById(elementId).innerText = event.target.result;
}

function onChooseFile(event, onLoadFileHandler) {
    if (typeof window.FileReader !== 'function')
        throw ("The file API isn't supported on this browser.");
    let input = event.target;
    if (!input)
        throw ("The browser does not properly implement the event object");
    if (!input.files)
        throw ("This browser does not support the `files` property of the file input.");
    if (!input.files[0])
        return undefined;
    let file = input.files[0];
    let fr = new FileReader();
    fr.onload = onLoadFileHandler;
    fr.readAsText(file);
}
<input type='file' onchange='onChooseFile(event, onFileLoad.bind(this, "contents"))' />
<p id="contents"></p>


Non funziona in Internet Explorer.
Merwais Muafaq

4

Buona programmazione!
Se ricevi un errore su Internet Explorer, modifica le impostazioni di sicurezza per consentire ActiveX

var CallBackFunction = function(content)
{
    alert(content);
}
ReadFileAllBrowsers(document.getElementById("file_upload"), CallBackFunction); 

//Tested in Mozilla Firefox browser, Chrome
function ReadFileAllBrowsers(FileElement, CallBackFunction)
{
try
{
    var file = FileElement.files[0];
    var contents_ = "";

     if (file) {
        var reader = new FileReader();
        reader.readAsText(file, "UTF-8");
        reader.onload = function(evt)
        {
            CallBackFunction(evt.target.result);
        }
        reader.onerror = function (evt) {
            alert("Error reading file");
        }
    }
}
catch (Exception)
 {
    var fall_back =  ieReadFile(FileElement.value);
    if(fall_back != false)
    {
        CallBackFunction(fall_back);
    }
 }
}

///Reading files with Internet Explorer
function ieReadFile(filename)
{
 try
 {
    var fso  = new ActiveXObject("Scripting.FileSystemObject");
    var fh = fso.OpenTextFile(filename, 1);
    var contents = fh.ReadAll();
    fh.Close();
    return contents;
 }
 catch (Exception)
  {
    alert(Exception);
    return false;
  }
 }

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.