Essayer d'utiliser fileReader.readAsBinaryString pour télécharger un fichier PNG sur le serveur via AJAX, code simplifié (fileObject est l'objet contenant les informations sur mon fichier);
var fileReader = new FileReader();
fileReader.onload = function(e) {
var xmlHttpRequest = new XMLHttpRequest();
//Quelques trucs AJAX - callbacks, gestionnaires, etc.
xmlHttpRequest.open("POST", '/pushfile', true);
var dashes = '--';
var boundary = 'aperturephotoupload';
var crlf = "\r\n";
//Postez avec le bon type MIME (si le système d'exploitation peut en identifier un)
if ( fileObject.type == '' ){
filetype = 'application/octet-stream';
} else {
filetype = fileObject.type;
}
//Construire une requête HTTP pour envoyer le fichier
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);
//Envoyer les données binaires
xmlHttpRequest.send(data);
}
fileReader.readAsBinaryString(fileObject);
Examiner les premières lignes d'un fichier avant de le télécharger (en utilisant VI) me donne
Le même fichier après le téléchargement montre
Il semble donc y avoir un problème de formatage/codage quelque part, j'ai essayé d'utiliser une simple fonction d'encodage UTF8 sur les données binaires brutes
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;
)
Ensuite, dans le code d'origine
//Construire une requête HTTP pour envoyer le fichier
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;
ce qui me donne la sortie de
Toujours pas ce qu'était le fichier brut =(
Comment encodage/charger/traiter le fichier pour éviter les problèmes d'encodage, afin que le fichier reçu dans la requête HTTP soit le même que le fichier avant d'être téléchargé.
Quelques autres informations potentiellement utiles, si au lieu d'utiliser fileReader.readAsBinaryString() j'utilise fileObject.getAsBinary() pour obtenir les données binaires, cela fonctionne bien. Mais getAsBinary ne fonctionne que dans Firefox. J'ai testé cela dans Firefox et Chrome, les deux sur Mac, obtenant le même résultat dans les deux cas. Les téléchargements côté serveur sont gérés par le Module de téléchargement NGINX, également en cours d'exécution sur Mac. Le serveur et le client sont sur la même machine. La même chose se produit avec n'importe quel fichier que j'essaie de télécharger, j'ai juste choisi PNG car c'était l'exemple le plus évident.