Beim Versuch, mit fileReader.readAsBinaryString eine PNG-Datei über AJAX auf den Server hochzuladen, wurde der Code reduziert (fileObject ist das Objekt, das Informationen zu meiner Datei enthält).
var fileReader = new FileReader();
fileReader.onload = function(e) {
var xmlHttpRequest = new XMLHttpRequest();
//Some AJAX-y stuff - callbacks, handlers etc.
xmlHttpRequest.open("POST", '/pushfile', true);
var dashes = '--';
var boundary = 'aperturephotoupload';
var crlf = "\r\n";
//Post with the correct MIME type (If the OS can identify one)
if ( fileObject.type == '' ){
filetype = 'application/octet-stream';
} else {
filetype = fileObject.type;
}
//Build a HTTP request to post the file
var data = dashes + boundary + crlf + "Content-Disposition: form-data;" + "name=\"file\";" + "filename=\"" + unescape(encodeURIComponent(fileObject.name)) + "\"" + crlf + "Content-Type: " + filetype + crlf + crlf + e.target.result + crlf + dashes + boundary + dashes;
xmlHttpRequest.setRequestHeader("Content-Type", "multipart/form-data;boundary=" + boundary);
//Send the binary data
xmlHttpRequest.send(data);
}
fileReader.readAsBinaryString(fileObject);
Das Untersuchen der ersten Zeilen einer Datei vor dem Hochladen (unter Verwendung von VI) gibt mir
Die gleiche Datei nach dem Hochladen wird angezeigt
Es sieht also nach einem Formatierungs- / Codierungsproblem aus. Ich habe versucht, eine einfache UTF8-Codierungsfunktion für die rohen Binärdaten zu verwenden
function utf8encode(string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
)
Dann im Originalcode
//Build a HTTP request to post the file
var data = dashes + boundary + crlf + "Content-Disposition: form-data;" + "name=\"file\";" + "filename=\"" + unescape(encodeURIComponent(file.file.name)) + "\"" + crlf + "Content-Type: " + filetype + crlf + crlf + utf8encode(e.target.result) + crlf + dashes + boundary + dashes;
das gibt mir die Ausgabe von
Immer noch nicht, was die Rohdatei war = (
Wie codiere / lade / verarbeite ich die Datei, um die Codierungsprobleme zu vermeiden, sodass die in der HTTP-Anforderung empfangene Datei mit der Datei vor dem Hochladen identisch ist.
Einige andere möglicherweise nützliche Informationen: Wenn ich anstelle von fileReader.readAsBinaryString () fileObject.getAsBinary () verwende, um die Binärdaten abzurufen, funktioniert dies einwandfrei. GetAsBinary funktioniert jedoch nur in Firefox. Ich habe dies in Firefox und Chrome getestet, beide auf Mac, und in beiden das gleiche Ergebnis erzielt. Die Backend-Uploads werden vom NGINX-Upload-Modul verarbeitet , das wiederum auf dem Mac ausgeführt wird. Der Server und der Client befinden sich auf demselben Computer. Das gleiche passiert mit jeder Datei, die ich hochladen möchte. Ich habe mich nur für PNG entschieden, weil dies das offensichtlichste Beispiel war.
quelle
<input type="file">
Feld hochgeladen worden wäre )(Es folgt eine späte, aber vollständige Antwort)
Unterstützung für FileReader-Methoden
FileReader.readAsBinaryString()
ist veraltet. Benutze es nicht! Es ist nicht mehr im Arbeitsentwurf der W3C-Datei-API enthalten :NB: Beachten Sie, dass dies
File
eine Art erweiterteBlob
Struktur ist.Mozilla implementiert
readAsBinaryString()
und beschreibt es weiterhin in der MDN FileApi-Dokumentation :Der Grund für die
readAsBinaryString()
Ablehnung ist meiner Meinung nach der folgende: Der Standard für JavaScript-Zeichenfolgen ist,DOMString
dass nur UTF-8-Zeichen akzeptiert werden, NICHT zufällige Binärdaten. Verwenden Sie also nicht readAsBinaryString (), das ist nicht sicher und ECMAScript-kompatibel.Wir wissen, dass JavaScript-Zeichenfolgen keine Binärdaten speichern sollen , Mozilla jedoch in irgendeiner Weise. Das ist meiner Meinung nach gefährlich.
Blob
undtyped arrays
(ArrayBuffer
und die noch nicht implementierten, aber nicht notwendigenStringView
) wurden für einen Zweck erfunden: die Verwendung von reinen Binärdaten ohne Einschränkungen der UTF-8-Zeichenfolgen zu ermöglichen.Unterstützung für das Hochladen von XMLHttpRequest
XMLHttpRequest.send()
hat die folgenden Aufrufoptionen:XMLHttpRequest.sendAsBinary()
hat die folgenden Aufrufoptionen:sendAsBinary () ist KEIN Standard und wird in Chrome möglicherweise nicht unterstützt.
Lösungen
Sie haben also mehrere Möglichkeiten:
send()
dieFileReader.result
vonFileReader.readAsArrayBuffer ( fileObject )
. Die Manipulation ist komplizierter (Sie müssen dafür ein separates send () erstellen ), aber es ist der EMPFOHLENE ANSATZ .send()
dieFileReader.result
vonFileReader.readAsDataURL( fileObject )
. Es erzeugt nutzlosen Overhead und Komprimierungslatenz, erfordert einen Dekomprimierungsschritt auf der Serverseite, ABER es ist einfach, als Zeichenfolge in Javascript zu manipulieren.sendAsBinary()
dasFileReader.result
vonFileReader.readAsBinaryString( fileObject )
MDN gibt an, dass:
quelle
FileReader.readAsDataURL
über denonload
Handler erfolgt, anstatt nur dieevent.target.result
(die keine saubere base64-codierte Zeichenfolge ist) Sie zu senden Bereinigen Sie es zuerst mit einem regulären Ausdruck wieevent.target.result = event.target.result.match(/,(.*)$/)[1]
und senden Sie die echte base64 an den Server, um sie zu dekodieren.event.target.result.split(",", 2)[1]
, nichtmatch
.Der beste Weg in Browsern, die dies unterstützen, besteht darin, die Datei als Blob zu senden oder FormData zu verwenden, wenn Sie ein mehrteiliges Formular wünschen. Sie benötigen dafür keinen FileReader. Dies ist sowohl einfacher als auch effizienter als der Versuch, die Daten zu lesen.
Wenn Sie es speziell als senden möchten
multipart/form-data
, können Sie ein FormData-Objekt verwenden:Sie können die Daten auch direkt senden, anstatt sie zu verwenden
multipart/form-data
. Siehe die Dokumentation . Dies erfordert natürlich auch eine serverseitige Änderung.Informationen zur Browserunterstützung finden Sie unter: http://caniuse.com/#feat=xhr2 (die meisten Browser, einschließlich IE 10+).
quelle
FormData
. Es scheint, dass jeder ein Formular verwendet, während er nur eine einzelne Datei hochladen muss ... Danke!