0

始める前に: これは 100% クライアント側の質問です。サーバー側の言語、アップロードの処理方法などは忘れてください-既知の動作するHTTPファイルアップロードリクエストと、理論的には同じことを行うはずのjQueryで生成されたAJAXリクエストを比較しています。

背景: tinyMCE 用のファイル アップロード プラグインを作成しています。これには、ドラッグ アンド ドロップをサポートするブラウザーで画像をアップロードできるようにすることも含まれます。具体的には、firefox の tinyMCE は、ファイル システムの画像が tinyMCE エディターにドロップされると、base64 src を使用して img を作成します。それが私の現在のユースケースです。後で拡張される可能性があります。

私の目標は、base64 データを取得し、jQuery を使用してフォーム送信をエミュレートし、サーバーにアップロードすることです。私はすでに、動作している通常の HTML フォームベースのアプローチを持っています。

base64 データを取得するのは簡単です。

$('img[src^="data:"]', ed.getDoc()).each(function(){
    var data = /data:(image\/\w+);base64,(.*)/gmi.exec(this.src), format, ext;
    if (data){
        format = data[1];
        ext = format.split('/')[1];
        data = atob(data[2]);
    }
    else{
        // blah, not supported
    }
});

POST データの準備も同様に簡単です。

var boundary = '--------------------boundary' + (new Date).getTime();
data = '\r\n' + boundary + '\r\n' +
        'Content-Disposition: form-data; name="file-upload"; filename="uploaded_image.' + ext + '"\r\n' +
        'Content-Type: ' + format + '\r\n\r\n' +
        data + '\r\n' +
        boundary + '--'
        ;

あとは、サーバーに送信するだけです。

$.ajax({
    type: 'POST',
    url: '/upload/',
    contentType: 'multipart/form-data; boundary=' + boundary.slice(2),
    data: data
});

サーバーは POST を「正しく」処理します (ファイルを認識してディスクに正常に保存します) が、結果の画像はかなり破損しています。ブラウザに表示されず、そのjpeg ヘッダーは完全に間違っています。ローカルよりも約 33% 大きいことに注意してください (サーバー上の 12K とローカルの 9K)。

charset=UTF-8Firebug の [Net] タブを使用すると、何も問題がないように見えます。実際、 Content-Type リクエスト ヘッダーの余分な部分と、きれいに印刷された POST データがないことを除けば、この AJAX リクエストは、対応するフォーム POSTとまったく同じように見えます。ただし、 HttpFoxを使用すると、別の話になります。

フォームのアップロード:

-----------------------------191891488320550623041315726177
Content-Disposition: form-data; name="file-upload"; filename="file.jpg"
Content-Type: image/jpeg

ÿØÿàJFIFHHÿÛC...

ajax アップロード:

--------------------boundary1375846064929
Content-Disposition: form-data; name="file-upload"; filename="file.jpeg"
Content-Type: image/jpeg

ÿÃÿà JFIFHHÿÃC...

また、リクエストの Content-Length の値が約 33% 異なることにも気付きました。なんらかの理由で、jQuery によって生成された POST リクエストが実際には UTF-8 で送信されないように見えますか? このパズルの最後のピースは何ですか?

4

1 に答える 1

5

解決策は、型付き配列と XHR2を使用することであることが判明しましたFormData(ポリフィルは両方で利用できますが、現在はどちらも重要なネイティブ サポートを享受しています)。

images.each(function(){
    var image = this,
        data = /data:(image\/\w+);base64,(.*)/gmi.exec(this.src),
        format, ext, binary;
    if (data){
        format = data[1];
        ext = format.split('/')[1];
        binary = atob(data[2]);
        data = new Uint8Array(binary.length);
        for (var i=0; i<binary.length; i++)
            data[i] = binary.charCodeAt(i);
    }
    else {
        // blah, not supported
    }

    var fd = new FormData();
    fd.append('file-upload', new Blob([data], {type: format}), 'uploaded_image.' + ext);

    $.ajax({
        type: 'POST',
        url: '/upload/',
        data: fd,
        processData: false,
        contentType: false
    });
});
于 2013-08-08T20:57:36.117 に答える