1. ホーム
  2. javascript

[解決済み] fileReader.readAsBinaryString によるファイルのアップロード

2023-06-04 09:35:07

質問

AJAX経由でサーバーにPNGファイルをアップロードするためにfileReader.readAsBinaryStringを使用しようとすると、コードを削除しました(fileObjectは私のファイルに関する情報を含むオブジェクトです)。

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);

アップロード前のファイルの最初の数行を調べると(VIを使用)、次のようになります。

アップロード後の同じファイルには

ということは、どこかでフォーマットやエンコードの問題が発生しているようなので、生のバイナリデータに対して単純な UTF8 エンコード関数を使用してみました。

    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;
    )

次に、元のコードでは

//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;

という出力が得られます。

まだ生ファイルが何であったかわからない =(

どのようにファイルをエンコード/ロード/処理すれば、エンコードの問題を回避でき、HTTP リクエストで受信されるファイルはアップロードされる前のファイルと同じになりますか。

fileReader.readAsBinaryString() を使用する代わりに fileObject.getAsBinary() を使用してバイナリ データを取得する場合、それは問題なく動作します。しかし、getAsBinaryはFirefoxでのみ動作します。MacのFirefoxとChromeでテストしていますが、どちらも同じ結果になります。バックエンドのアップロードは NGINX アップロードモジュール によって処理されています。サーバーとクライアントは同じマシンにあります。アップロードしようとするどのファイルでも同じことが起こりますが、最も明白な例だったので PNG を選択しました。

どのように解決するのですか?

使用方法 fileReader.readAsDataURL( fileObject ) これでbase64にエンコードされ、安全にサーバーにアップロードできるようになります。