610

jQuery の ajax 関数を使用して、サーバー側の PHP スクリプトにファイルを送信する際に問題が発生しました。File-List を取得すること$('#fileinput').attr('files')は可能ですが、このデータをサーバーに送信するにはどうすればよいでしょうか? ファイル入力を使用する場合$_POST、サーバー側の php-scriptの結果の配列 ( ) は 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);
    }
});
4

13 に答える 13

934

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']

file-0(ファイル入力で属性を指定しない限り、ファイルは1つだけです。指定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']これにより、アップロードされたすべてのファイルのファイルアップロードフィールドを含む配列になります。反復する方が簡単なので、最初のソリューションよりも実際にこれをお勧めします。

于 2011-05-12T09:36:09.957 に答える
61

私のコードを見てください、それは私のために仕事をします

$( '#formId' )
  .submit( function( e ) {
    $.ajax( {
      url: 'FormSubmitUrl',
      type: 'POST',
      data: new FormData( this ),
      processData: false,
      contentType: false
    } );
    e.preventDefault();
  } );
于 2014-08-30T06:49:40.433 に答える
51

ラファエルの素晴らしい答えに少し付け加えたかっただけです。$_FILESJavaScriptを使用して送信するかどうかに関係なく、PHPで同じものを生成する方法は次のとおりです。

HTMLフォーム:

<form enctype="multipart/form-data" action="/test.php" 
method="post" class="putImages">
   <input name="media[]" type="file" multiple/>
   <input class="button" type="submit" alt="Upload" value="Upload" />
</form>

$_FILESJavaScriptなしで送信すると、PHPはこれを生成します。

Array
(
    [media] => Array
        (
            [name] => Array
                (
                    [0] => Galata_Tower.jpg
                    [1] => 518f.jpg
                )

            [type] => Array
                (
                    [0] => image/jpeg
                    [1] => image/jpeg
                )

            [tmp_name] => Array
                (
                    [0] => /tmp/phpIQaOYo
                    [1] => /tmp/phpJQaOYo
                )

            [error] => Array
                (
                    [0] => 0
                    [1] => 0
                )

            [size] => Array
                (
                    [0] => 258004
                    [1] => 127884
                )

        )

)

プログレッシブエンハンスメントを行う場合は、RaphaelのJSを使用してファイルを送信します...

var data = new FormData($('input[name^="media"]'));     
jQuery.each($('input[name^="media"]')[0].files, function(i, file) {
    data.append(i, file);
});

$.ajax({
    type: ppiFormMethod,
    data: data,
    url: ppiFormActionURL,
    cache: false,
    contentType: false,
    processData: false,
    success: function(data){
        alert(data);
    }
});

...これは$_FILES、JavaScriptを使用して送信した後のPHPの配列のようになります。

Array
(
    [0] => Array
        (
            [name] => Galata_Tower.jpg
            [type] => image/jpeg
            [tmp_name] => /tmp/phpAQaOYo
            [error] => 0
            [size] => 258004
        )

    [1] => Array
        (
            [name] => 518f.jpg
            [type] => image/jpeg
            [tmp_name] => /tmp/phpBQaOYo
            [error] => 0
            [size] => 127884
        )

)

これは素晴らしい配列であり、実際には何人かの人々が変換するものですが、JavaScriptが送信に使用されたかどうかに関係なく$_FILES、同じもので作業することは有用だと思います。$_FILESしたがって、JSに対するいくつかのマイナーな変更があります。

// match anything not a [ or ]
regexp = /^[^[\]]+/;
var fileInput = $('.putImages input[type="file"]');
var fileInputName = regexp.exec( fileInput.attr('name') );

// make files available
var data = new FormData();
jQuery.each($(fileInput)[0].files, function(i, file) {
    data.append(fileInputName+'['+i+']', file);
});

(2017年4月14日編集:FormData()のコンストラクターからform要素を削除しました-Safariでこのコードを修正しました。)

そのコードは2つのことを行います。

  1. inputname属性を自動的に取得し、HTMLをより保守しやすくします。これでform、クラスputImagesがある限り、他のすべてが自動的に処理されます。つまり、input特別な名前を付ける必要はありません。
  2. 通常のHTMLが送信する配列形式は、JavaScriptによってdata.append行に再作成されます。角かっこに注意してください。

これらの変更により、JavaScriptを使用し$_FILESて送信すると、単純なHTMLを使用して送信した場合とまったく同じ配列が生成されるようになりました。

于 2012-01-10T00:56:40.453 に答える
47

読んだ情報に基づいてこの関数を作成しました。

を使用するのと同じように使用して.serialize()ください.serializefiles();
私のテストでここで働いています。

//USAGE: $("#form").serializefiles();
(function($) {
$.fn.serializefiles = function() {
    var obj = $(this);
    /* ADD FILE TO PARAM AJAX */
    var formData = new FormData();
    $.each($(obj).find("input[type='file']"), function(i, tag) {
        $.each($(tag)[0].files, function(i, file) {
            formData.append(tag.name, file);
        });
    });
    var params = $(obj).serializeArray();
    $.each(params, function (i, val) {
        formData.append(val.name, val.value);
    });
    return formData;
};
})(jQuery);
于 2012-09-14T14:33:12.680 に答える
24

フォームが HTML で定義されている場合、反復して画像を追加するよりも、フォームをコンストラクターに渡す方が簡単です。

$('#my-form').submit( function(e) {
    e.preventDefault();

    var data = new FormData(this); // <-- 'this' is your form element

    $.ajax({
            url: '/my_URL/',
            data: data,
            cache: false,
            contentType: false,
            processData: false,
            type: 'POST',     
            success: function(data){
            ...
于 2014-06-02T17:43:39.753 に答える
12

Devin Venable の答えは私が望んでいたものに近かったのですが、複数のフォームで機能し、フォームで既に指定されているアクションを使用して、各ファイルが適切な場所に移動するものを求めていました。

また、jQuery の on() メソッドを使用したかったので、.ready() の使用を避けることができました。

それは私にこれをもたらしました:(formSelectorをあなたのjQueryセレクターに置き換えてください)

$(document).on('submit', formSelecter, function( e ) {
        e.preventDefault();
    $.ajax( {
        url: $(this).attr('action'),
        type: 'POST',
        data: new FormData( this ),
        processData: false,
        contentType: false
    }).done(function( data ) {
        //do stuff with the data you got back.
    });

});
于 2016-06-15T16:54:52.433 に答える
1

FormData クラスは機能しますが、iOS Safari (少なくとも iPhone 上) では、Raphael Schweikert のソリューションをそのまま使用できませんでした。

Mozilla Dev にはFormData オブジェクトの操作に関するすばらしいページがあります。

したがって、enctype を指定して、ページのどこかに空のフォームを追加します。

<form enctype="multipart/form-data" method="post" name="fileinfo" id="fileinfo"></form>

次に、 FormData オブジェクトを次のように作成します。

var data = new FormData($("#fileinfo"));

ラファエルのコードのように進みます。

于 2013-02-22T00:24:13.713 に答える
1

今日遭遇した 1 つの落とし穴は、この問題に関連して指摘する価値があると思います: ajax 呼び出しの URL がリダイレクトされると、content-type: 'multipart/form-data' のヘッダーが失われる可能性があります。

たとえば、私はhttp://server.com/context?param=xに投稿していました

Chrome のネットワーク タブで、このリクエストの正しいマルチパート ヘッダーが表示されましたが、302 リダイレクトがhttp://server.com/context/?param=xに表示されました(コンテキストの後のスラッシュに注意してください)。

リダイレクト中に、マルチパート ヘッダーが失われました。これらのソリューションが機能しない場合は、リクエストがリダイレクトされていないことを確認してください。

于 2016-03-17T22:07:16.083 に答える
-2
  1. jquery-> $("#id")[0] でフォームオブジェクトを取得
  2. data = new FormData($("#id")[0]);
  3. わかりました、データはあなたが欲しいです
于 2013-07-18T09:54:58.757 に答える