1. ホーム
  2. jquery

[解決済み] jQuery.ajaxでmultipart/formdataを送信する。

2022-03-17 01:14:41

質問

jQueryのajax機能を使って、サーバーサイドのPHPスクリプトにファイルを送信する際に問題が発生しました。 ファイルリストを取得することは可能です。 $('#fileinput').attr('files') このデータをサーバーに送るにはどうすればいいのでしょうか?結果として得られる配列 ( $_POST ) サーバーサイドのphpスクリプトでは、0 ( NULL ) を使用する場合、ファイル入力はできません。

可能であることは知っています(ただし、今までjQueryの解決策は見つからず、Prototyeのコードのみ( http://webreflection.blogspot.com/2009/03/safari-4-multiple-upload-with-progress.html )).

これは比較的新しいようなので、XHR/Ajax経由のファイルアップロードが不可能であることは言及しないでください。

Safari 5での機能が必要です。FFとChromeがあれば良いのですが、必須ではありません。

今のところ私のコードは

$.ajax({
    url: 'php/upload.php',
    data: $('#file').attr('files'),
    cache: false,
    contentType: 'multipart/form-data',
    processData: false,
    type: 'POST',
    success: function(data){
        alert(data);
    }
});

解決方法は?

Safari 5/Firefox 4 以降では、最も簡単な方法で FormData クラスがあります。

var data = new FormData();
jQuery.each(jQuery('#file')[0].files, function(i, file) {
    data.append('file-'+i, file);
});

ということで、今度は FormData オブジェクトを作成し、XMLHttpRequest と共に送信できるようにします。

jQuery.ajax({
    url: 'php/upload.php',
    data: data,
    cache: false,
    contentType: false,
    processData: false,
    method: 'POST',
    type: 'POST', // For jQuery < 1.9
    success: function(data){
        alert(data);
    }
});

を設定することが必須です。 contentType オプションを false を追加しないようにjQueryに強制しています。 Content-Type ヘッダを作成します。そうしないと、境界文字列が欠落してしまいます。 また processData フラグを false に設定しないと、jQuery はあなたの FormData を文字列に変換しますが、これは失敗します。

これで、PHPでファイルを取得することができます。

$_FILES['file-0']

(ファイルは1つだけです。 file-0 を指定しない限り multiple 属性があり、その場合、数字はファイルごとに増加します)。

を使用すると FormDataのエミュレーション 古いブラウザ用

var opts = {
    url: 'php/upload.php',
    data: data,
    cache: false,
    contentType: false,
    processData: false,
    method: 'POST',
    type: 'POST', // For jQuery < 1.9
    success: function(data){
        alert(data);
    }
};
if(data.fake) {
    // Make sure no text encoding stuff is done by xhr
    opts.xhr = function() { var xhr = jQuery.ajaxSettings.xhr(); xhr.send = xhr.sendAsBinary; return xhr; }
    opts.contentType = "multipart/form-data; boundary="+data.boundary;
    opts.data = data.toString();
}
jQuery.ajax(opts);

既存のフォームからFormDataを作成する

手動でファイルを反復する代わりに、既存のフォームオブジェクトの内容で FormData オブジェクトを作成することもできます。

var data = new FormData(jQuery('form')[0]);

カウンターの代わりに PHP ネイティブの配列を使用します。

ファイル要素の名前を同じにして、名前の最後を括弧で囲むだけです。

jQuery.each(jQuery('#file')[0].files, function(i, file) {
    data.append('file[]', file);
});

$_FILES['file'] は、アップロードされたすべてのファイルのファイルアップロードフィールドを含む配列になります。私は、反復処理がより単純になるため、最初の解決策よりもこの方法を実際にお勧めします。