Lesen von Dateiinhalten auf der Clientseite in Javascript in verschiedenen Browsern

112

Ich versuche, eine reine Skriptlösung zum Lesen des Inhalts einer Datei auf einem Clientcomputer über einen Browser bereitzustellen.

Ich habe eine Lösung, die mit Firefox und Internet Explorer funktioniert. Es ist nicht schön, aber ich probiere gerade nur Dinge aus:

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 :(";
    }
}

Ich kann anrufen getFileContents()und es wird den Inhalt in den fileContentsTextbereich schreiben .

Gibt es eine Möglichkeit, dies in anderen Browsern zu tun?

Ich bin im Moment am meisten mit Safari und Chrome beschäftigt, aber ich bin offen für Vorschläge für jeden anderen Browser.

Bearbeiten: Als Antwort auf die Frage "Warum möchten Sie das tun?":

Grundsätzlich möchte ich den Dateiinhalt zusammen mit einem Einmalkennwort auf der Clientseite hashen, damit ich diese Informationen zur Bestätigung zurücksenden kann.

Damovisa
quelle
Nicht, dass ich eine Antwort habe, sondern nur aus Gründen der Klarheit, müssen Sie den Speicherort der Datei kennen? Wenn nicht, muss der Speicherort der Datei aus einer Dateieingabe gelesen werden oder kann es sich um ein Textfeld / einen Textbereich / was auch immer handeln?
Darko Z
Gute Frage. Nein, es ist mir eigentlich egal, woher die Datei kommt, nur der Inhalt. Die Verwendung einer Dateieingabe erscheint mir jedoch sinnvoll, da es sich um natives HTML handelt - eines muss ich weniger tun.
Damovisa
warum willst du das überhaupt machen Der Server soll das tun.
Geowa4
Kurz gesagt: Ein Benutzer gibt ein Passwort ein und wählt eine Datei aus. Das Kennwort wird mit dem Dateiinhalt gehasht und zusammen mit der Datei an den Server gesendet. Wenn es dort ankommt, kann ich überprüfen, ob das richtige Client-Passwort verwendet wurde.
Damovisa

Antworten:

157

Bearbeitet, um Informationen zur Datei-API hinzuzufügen

Seit ich diese Antwort ursprünglich geschrieben habe, wurde die Datei-API als Standard vorgeschlagen und in den meisten Browsern implementiert (ab IE 10, der FileReaderdie hier beschriebene API- Unterstützung hinzufügte , jedoch noch nicht die FileAPI). Die API ist etwas komplizierter als die ältere Mozilla-API, da sie das asynchrone Lesen von Dateien, die bessere Unterstützung von Binärdateien und das Dekodieren verschiedener Textcodierungen unterstützt. Im Mozilla Developer Network sind einige Dokumentationen sowie verschiedene Beispiele online verfügbar. Sie würden es wie folgt verwenden:

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

Ursprüngliche Antwort

In WebKit (also Safari und Chrome) scheint es keine Möglichkeit zu geben, dies zu tun. Die einzigen Schlüssel, die ein Dateiobjekt hat, sind fileNameund fileSize. Gemäß der Commit - Nachricht für die Datei und Filelist - Unterstützung, werden diese durch inspiriert Mozillas File - Objekt , aber sie scheinen nur einen Teil der Funktionen zu unterstützen.

Wenn Sie dies ändern möchten, können Sie jederzeit einen Patch an das WebKit-Projekt senden . Eine andere Möglichkeit wäre, die Mozilla-API für die Aufnahme in HTML 5 vorzuschlagen . Die WHATWG- Mailingliste ist wahrscheinlich der beste Ort dafür. Wenn Sie dies tun, ist es viel wahrscheinlicher, dass es zumindest in ein paar Jahren einen browserübergreifenden Weg gibt, dies zu tun. Das Einreichen eines Patches oder eines Vorschlags zur Aufnahme in HTML 5 bedeutet natürlich einige Arbeit, um die Idee zu verteidigen, aber die Tatsache, dass Firefox sie bereits implementiert, gibt Ihnen zunächst etwas.

Brian Campbell
quelle
Vielen Dank dafür - ich glaube, ich bin derzeit nicht engagiert genug, um einen Patch einzureichen. Es ist etwas, das Sie ohne Ihr Wissen wahrscheinlich sowieso nicht wollen würden. Es bricht irgendwie die Browser-Sandbox ...
Damovisa
4
Die Browser-Sandbox wird dadurch nicht beschädigt, da Sie diese Datei absichtlich hochgeladen haben. Wenn es zum Server gelangen kann, kann es mit einem zusätzlichen Roundtrip zum Browser zurückkehren. Angesichts der Arbeit, mit der der Offline-Modus für Web-Apps funktioniert, wäre dies eine vernünftige Funktion.
Brian Campbell
Mm, eigentlich ist das ein fairer Punkt. Es gab eine Benutzerinteraktion, um diese Datei auszuwählen. Vielen Dank.
Damovisa
@Damovisa Ich weiß nicht, ob Sie sich noch dafür interessieren, aber ich dachte mir, ich würde meine Antwort aktualisieren, um die neue Datei-API zu erwähnen, die genau das tut, wonach Sie suchen, und die in Firefox, Chrome und nächtlichen Builds von implementiert ist Safari.
Brian Campbell
Super, danke dafür. Ich bin zu einer anderen Arbeit
übergegangen
24

Um eine vom Benutzer ausgewählte Datei in einem Dialogfeld zum Öffnen von Dateien zu lesen, können Sie das <input type="file">Tag verwenden. Informationen dazu finden Sie bei MSDN . Wenn die Datei ausgewählt ist, können Sie den Inhalt mithilfe der FileReader-API lesen.

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>

cdiggins
quelle
Funktioniert nicht im Internet Explorer.
Merwais Muafaq
4

Viel Spaß beim Codieren!
Wenn im Internet Explorer eine Fehlermeldung angezeigt wird, ändern Sie die Sicherheitseinstellungen, um ActiveX zuzulassen

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;
  }
 }
Mnyikka
quelle