Wie kann eine lokale CSV-Datei vor dem Hochladen auf einen Server verarbeitet werden?

Ich versuche, eine Webseite einzurichten, auf der vertrauenswürdige Benutzer lokale CSV-Dateien hochladen können, die von den Benutzern analysiert, validiert, überprüft und dann in verschiedene Tabellen in einer MySQL-Datenbank eingefügt werden.

Der Rest der Site wird mit PHP und jQuery geschrieben. Ich weiß, wie man eine CSV-Datei in PHP einliest und eine Abfrage generiert. Das Problem ist, dass die Validierung und Analyse der Datei interaktiv erfolgt. Der Benutzer muss nach verschiedenen Informationen zu den Daten gefragt werden, Spalten aus der Datei mit Feldern in der Datenbank abgleichen und die Möglichkeit erhalten, diese zu überprüfen und zu aktualisieren Antworten, bis sie sicher sind, dass alles korrekt ist.

Es scheint so, als würde in den 90er Jahren jedes Mal, wenn der Benutzer etwas ändert, die ganze Seite neu geladen. Ich nahm an, dass AJAX die Art und Weise ist, dies clientseitig zu tun, aber es scheint, dass das Öffnen lokaler Dateien aus "Sicherheitsgründen" von Browsern speziell verhindert wird. .

Meine Frage ist:

Gibt es ein allgemein akzeptiertes Muster, nach dem ein Benutzer auf der Grundlage des Inhalts einer Datei sicher und effizient Entscheidungen treffen kann, bevor die Datei tatsächlich auf den Server hochgeladen wird? Oder senden die Leute in solchen Situationen wirklich nur Dutzende von POST-Anfragen?

Übrigens verwenden wir kein Windows oder irgendetwas Closed-Source, daher kann sich die Lösung leider nicht auf Internet Explorer oder ActiveX verlassen.

Vielen Dank.

 bokov04. Apr. 2012, 23:46
Ja genau. Also frage ich mich, wie man die Datei clientseitig trennen kann.
 bokov04. Apr. 2012, 23:53
Ich meine, muss ich die Datei wirklich als POST an den Server senden, muss der Server die Kopfzeile erraten und den Benutzer fragen, ob es die richtige ist, und dann einen weiteren POST senden, bei dem der Benutzer die richtige Kopfzeile angegeben hat, damit sie korrekt ist Spaltennamen können angezeigt werden, und dann ein weiterer POST, bei dem der Benutzer die Spaltennamen mit den Feldern vergleicht, zu denen er gehen soll? Die gesamte Datei wird dreimal gesendet und zwei Mal werden nur ein paar Zeilen gelesen.
 Marc B04. Apr. 2012, 23:43
Sie müssten dem Benutzer das Hochladen der Datei noch überlassen, diese jedoch trennen, bis der Benutzer mit seinen Manipulationen fertig ist. erst dann 'festschreiben' Sie die Datei, wohin sie gehen muss.
 Marc B04. Apr. 2012, 23:49
Da es die Clients sind, die die Datei hochladen, liegt es vermutlich an ihnen, die Dinge auf ihrem eigenen Computer getrennt zu halten. Wenn Sie die Uploads auf dem Server getrennt halten möchten, hängt dies von Ihrem Upload-Handler ab. Speichere sie in ein Arbeitsverzeichnis für die Überprüfungsphase. Wenn sich der Benutzer von der Datei abmeldet, verschieben Sie sie an das endgültige Ziel.
 Gats04. Apr. 2012, 23:47
Nein, es gibt nicht wirklich etwas anderes als ein Plugin wie Flash. In dieser Situation ist es durchaus üblich, dass ein Benutzer eine Datei wie ein Bild bearbeiten und dann das Ergebnis oder die Originaldatei mit Änderungen als XML oder ähnliches hochladen kann. Es wäre ein massives Sicherheitsproblem, wenn Javascript Dateien auf dem Computer des Benutzers überprüfen könnte und dies nicht möglich wäre. Sie können aus diesem Grund nicht einmal eine Datei mit Javascript ohne ein Plugin posten.

Antworten auf die Frage(4)

HTML:

<code><form id = "emailform" action = "admincsvupload" role="form" method="post" enctype="multipart/form-data">
<div class="form-group">
<label class="sr-only" for="csvfile">Upload CSV</label>
<input type="file" name = "csvfile" class="form-control" id="csvfile" placeholder="Select CSV file">                 
</div>
<button type="button" class="btn btn-success" id="btnLoad">Load</button>
<button type="submit" class="btn btn-success" id="btnSubmit" style="display:none">Upload Now!</button>
</form>
</code>

0%

Javascript:

<code>  // File load as HTMl n a table before actuly upload it on the server



    function updateProgress(evt) {
    // evt is an ProgressEvent.
    if (evt.lengthComputable) {
        var percentLoaded = Math.round((evt.loaded / evt.total) * 100);
        // Increase the progress bar length.
        if (percentLoaded < 100) {
            progress.style.width = percentLoaded + '%';
            progress.textContent = percentLoaded + '%';
        }
    }
}

     function readBlob(opt_startByte, opt_stopByte) {
    var progress = document.querySelector('.percent');
    var files = document.getElementById('csvfile').files;
    if (!files.length) {
        alert('Please select a file!');
        return;
    }

    var file = files[0];
    var start = 0;
    var stop = file.size - 1;
    progress.style.width = '0%';
    progress.textContent = '0%';
    var reader = new FileReader();

    //Reader progress 
    reader.onprogress = updateProgress;

    // If we use onloadend, we need to check the readyState.
    reader.onloadend = function (evt) {
        if (evt.target.readyState == FileReader.DONE) { // DONE == 2
            var data = evt.target.result;
            var delimiter = ',';
            var escape = '\n';
            var rows = data.split(escape);
            var tbl = document.createElement('table');
            tbl.style.width = '100%';
            //tbl.setAttribute('border', '1', "green");
            tbl.className = "table table-hover table-condensed dataTable";
            var tbdy = document.createElement('tbody');

            for (index in rows) {
                var tr = document.createElement('tr'); // creating new row 
                var items = rows[index].split(delimiter);
                for (itemindex in items) {
                    var td = "";
                    if (index == 0) {
                        td = document.createElement('th');
                    } else {
                        td = document.createElement('td');
                    }

                    td.appendChild(document.createTextNode(items[itemindex])); // creating new cell 
                    tr.appendChild(td); // add to current tr
                }

                tbdy.appendChild(tr); // add new row (tr) to table 
            }
            tbl.appendChild(tbdy);

            document.getElementById('byte_content').innerHTML=tbl;

        }
    };

    // Progress Loading
    reader.onloadstart = function(e) {
      document.getElementById('progress_bar').className = 'loading';
    };


    reader.onload = function(e) {
      // Ensure that the progress bar displays 100% at the end.
      progress.style.width = '100%';
      progress.textContent = '100%';
      setTimeout("document.getElementById('progress_bar').className='';", 2000);
    }
    var blob = file.slice(start, stop + 1);
    reader.readAsBinaryString(blob);
    document.querySelector('#btnLoad').style.display = "none";
    document.getElementById("btnSubmit").style.display = "block";


}

//Change event if user select a new file.
document.querySelector('#csvfile').addEventListener('change', function (evt) {
        return readBlob();

}, false);
</code>

Ein Beispiel für eine effiziente Ausführung finden Sie in derPapa Parse Bibliothek.

Es kann sehr große Dateien problemlos verarbeiten.

Lösung für das Problem

Sie müssen keine Anfrage an den Server stellen, wenn Sie die Javascript FileReader API verwenden, die ab Firefox 3.6 und Chrome 7 verfügbar ist. Zum Glück gibt es wirklich interessante Artikel, die die Funktionsweise der API recht deutlich erklären.

http://www.html5rocks.com/de/tutorials/file/dndfiles/

Wenn Sie Bedenken hinsichtlich der Unterstützung der API in den verschiedenen Browsern haben, wird diese am Ende dieses anderen Artikels angezeigt:

https://developer.mozilla.org/en/DOM/FileReader

Ich habe diese API kürzlich zum Hochladen von Text- und Binärdateien verwendet. Zögern Sie also nicht, mich zu kontaktieren, wenn Sie es ausprobieren möchten und Zweifel haben.

 bokov09. Apr. 2012, 20:07
Das ist schön und funktioniert einwandfrei mit jQuery. Ich kann jetzt Dinge auf der Client-Seite tun, die ich vor kurzem für magisch gehalten hätte. Vielen Dank.
 txominpelu10. Apr. 2012, 00:15
Kein Problem! Das gleiche ist mir in letzter Zeit passiert. Es gibt viele Dinge mit Javascript und dem Browser und Seiten wiehtml5rocks und MozillasMDN Ich bin der Meinung, dass es eine großartige Aufgabe ist, sie zu erklären.

Sie haben zwei große Klassen von Lösungen:

Laden Sie die CSV hoch und verlassen Sie sich auf die serverseitige Logik, um die Transformationen durchzuführen und möglicherweise mit dem Benutzer zu interagieren. Dies kann das Laden einer Browserseite beinhalten, die die zweite Wahl nach dem Hochladen implementiert.Lassen Sie den Benutzer die Datei kopieren und in ein Textfeld des Browsers einfügen und verwenden Sie browserbasiertes Javascript oder Applets, um den Text zu transformieren, und interagieren Sie möglicherweise lokal oder mit einem Webserver.

Beides kann mit standardbasierten Implementierungen erfolgen. Die ungewöhnlichste Option ist die zweite Wahl, die sich auf das Kopieren / Einfügen durch den Benutzer stützt. Aus diesem Grund würden die meisten Implementierungen eine Variation der ersten Option wählen.

Wohin die Hauptlogik der Dateiumwandlung geht, liegt bei Ihnen. Es müssen dabei keine Sicherheitsprobleme auftreten, wenn vorsichtig vorgegangen wird.

Ihre Antwort auf die Frage