JQuery.ajax के साथ मल्टीपार्ट / फॉर्मडाटा भेजना


563

मुझे jQuery के अजाक्स-फ़ंक्शन का उपयोग करके सर्वर-आधारित PHP-स्क्रिप्ट में फ़ाइल भेजने में समस्या हुई है। फ़ाइल-सूची प्राप्त $('#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 के माध्यम से असंभव होगा, क्योंकि यह निश्चित रूप से काम कर रहा है।

मुझे सफारी 5 में कार्यक्षमता की आवश्यकता है, एफएफ और क्रोम अच्छा होगा लेकिन जरूरी नहीं है।

अब के लिए मेरा कोड है:

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

आमतौर पर FormData ऑब्जेक्ट का उपयोग IE <10 पर काम नहीं करता है।
एलेजांद्रो गार्सिया इग्लेसियस

@GarciaWebDev माना जाता है कि आप उसी API का समर्थन करने के लिए Flash के साथ पॉलीफ़िल का उपयोग कर सकते हैं। अधिक जानकारी के लिए github.com/Modernizr/Modernizr/wiki/… देखें ।
yuxhuang


3
आप $(':file')सभी इनपुट फ़ाइलों का चयन करने के लिए उपयोग कर सकते हैं । यह थोड़ा सरल है।
शाहर

@RameshwarVyevhare इस सवाल का जवाब देने के पांच साल बाद जवाब दिया गया था। कृपया अपने स्वयं के उत्तरों को बढ़ावा देने के लिए इसी तरह के प्रश्नों को ट्रोल न करें।
रयान पी

जवाबों:


882

सफारी 5 / फ़ायरफ़ॉक्स 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);
    }
});

यह अनिवार्य है कि आप jQuery को नहीं जोड़ने के लिए मजबूर contentTypeकरने के लिए विकल्प सेट करेंfalseContent-Type हेडर , अन्यथा, सीमा स्ट्रिंग इसके साथ गायब हो जाएगी। इसके अलावा, आपको processDataध्वज सेट को झूठे पर छोड़ना होगा , अन्यथा, jQuery आपके FormDataस्ट्रिंग में बदलने की कोशिश करेगा , जो विफल हो जाएगा।

अब आप PHP का उपयोग करके फ़ाइल को पुनः प्राप्त कर सकते हैं:

$_FILES['file-0']

(केवल एक फ़ाइल है, file-0 जब तक आप multipleअपने फ़ाइल इनपुट पर विशेषता निर्दिष्ट नहीं करते हैं , उस स्थिति में, संख्या आपकी फ़ाइल के साथ बढ़ेगी।)

पुराने ब्राउज़रों के लिए फ़ॉर्मडाटा एमुलेशन का उपयोग करना

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

एक मौजूदा फ़ॉर्म से फ़ॉर्मडाटा बनाएँ

फ़ाइलों को मैन्युअल रूप से पुनरावृत्त करने के बजाय, फॉर्मडाटा ऑब्जेक्ट को मौजूदा फॉर्म ऑब्जेक्ट की सामग्री के साथ भी बनाया जा सकता है:

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

एक काउंटर के बजाय एक PHP देशी सरणी का उपयोग करें

बस अपनी फ़ाइल तत्वों को समान नाम दें और कोष्ठक में नाम समाप्त करें:

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

$_FILES['file']फिर एक सरणी होगी जिसमें अपलोड की गई प्रत्येक फ़ाइल के लिए फ़ाइल अपलोड फ़ील्ड होगी। मैं वास्तव में इसे अपने प्रारंभिक समाधान पर सुझाता हूं क्योंकि यह अधिक से अधिक पुनरावृति करना आसान है।


2
इसके अलावा, एक फॉर्मडाटा एमुलेशन है जो पुराने उपयोगकर्ताओं के लिए इस समाधान को काफी सरल बना देगा। आपको बस इतना करना है कि उपयोग करने के लिए xr को ओवरराइड करने के साथ-साथ संपत्ति को मैन्युअल रूप से जांचना data.fakeऔर सेट contentTypeकरना है sendAsBinary()
राफेल श्विकर्ट

13
तो आप न तो कक्षा का उपयोग कर रहे हैं और न jQueryही FormDataआप मुझे jQuery के लिए विशिष्ट प्रश्न और फॉर्मडाटा का उपयोग करने के लिए विशिष्ट उत्तर के संदर्भ में पूछ रहे हैं? मुझे खेद है, लेकिन मुझे नहीं लगता कि मैं वहां आपकी मदद कर सकता हूं ...
राफेल स्कवीर्ट

3
यह उपयोग करता है application/x-www-form-urlencoded। क्या multipart/form-dataइसके बजाय उपयोग करने का कोई तरीका है ?
टिम्मम्म

4
@Timmmm नहीं, यह उपयोग करता है multipart/form-data। उपयोग application/x-www-form-urlencodedकरने से काम नहीं चलेगा।
राफेल श्विकर्ट

5
@RoyiNamir यह केवल कोड में प्रलेखित है , मुझे डर है।
राफेल श्विकर्ट

51

बस राफेल के महान जवाब के लिए थोड़ा जोड़ना चाहते थे। यहाँ PHP का उत्पादन करने के लिए कैसे प्राप्त करें$_FILES , भले आप जावास्क्रिप्ट को सबमिट करने के लिए उपयोग करें।

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>

$_FILESजावास्क्रिप्ट के बिना प्रस्तुत किए जाने पर 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
                )

        )

)

यदि आप प्रगतिशील वृद्धि करते हैं, तो फाइलों को जमा करने के लिए राफेल के जेएस का उपयोग करते हुए ...

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

... यह वही है जो PHP की $_FILESसरणी की तरह दिखता है, उस जावास्क्रिप्ट का उपयोग करने के बाद सबमिट करने के लिए:

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
        )

)

यह एक अच्छा सरणी है, और वास्तव में कुछ लोग किस रूप $_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);
});

(१४ अप्रैल २०१: संपादित करें: मैंने फॉर्मडैट के निर्माता से फार्म तत्व को हटा दिया () - जिसने सफारी में यह कोड तय किया।)

वह कोड दो काम करता है।

  1. inputनाम विशेषता को स्वचालित रूप से पुनर्प्राप्त करता है , जिससे HTML अधिक बनाए रखा जा सकता है। अब, जब तक formवर्ग पुटमेज है, तब तक बाकी सब कुछ स्वचालित रूप से ध्यान रखा जाता है। यह है कीinput जरूरत किसी खास नाम की नहीं है।
  2. सामान्य HTML सबमिट्स वाले सरणी प्रारूप को data.append लाइन में जावास्क्रिप्ट द्वारा पुनः बनाया जाता है। कोष्ठक पर ध्यान दें।

इन परिवर्तनों के साथ, जावास्क्रिप्ट के साथ सबमिट करने पर अब $_FILESसाधारण HTML के साथ सबमिट करने के समान ही सरणी का उत्पादन होता है ।


सफारी के साथ एक ही मुद्दा था। संकेत के लिए धन्यवाद!
१४:४२ बजे

49

मेरे कोड को देखो, यह मेरे लिए काम करता है

$( '#formId' )
  .submit( function( e ) {
    $.ajax( {
      url: 'FormSubmitUrl',
      type: 'POST',
      data: new FormData( this ),
      processData: false,
      contentType: false
    } );
    e.preventDefault();
  } );

इसने पूरी तरह से काम किया और इसे लागू करने के लिए बहुत सरल है।
Jh62

45

मैंने अभी इस फ़ंक्शन को कुछ जानकारी के आधार पर बनाया है जो मैंने पढ़ा है।

इसे इस्तेमाल करने की तरह ही इस्तेमाल करें .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);

2
मैं इस काम को पाने की कोशिश कर रहा था, लेकिन यह एक समारोह के रूप में सीरीज़इफ़ाइल्स () को मान्यता नहीं दे रहा था, इस परिभाषा के बावजूद पृष्ठ के शीर्ष पर जा रहा था।
15

1
यह मेरे लिए ठीक काम करता है। साथ डेटा प्राप्त करने var data = $("#avatar-form").serializefiles();ajax डेटा पैरामीटर के माध्यम से इस भेजने और एक्सप्रेस दुर्जेय साथ विश्लेषण करने: form.parse(req, function(err, fields, files){आप उस कोड स्निपेट के लिए :) धन्यवाद
SchurigH

23

यदि आपके फॉर्म को आपके 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){
            ...

9

डेविन वेनटेबल का जवाब था कि मैं क्या चाहता था, लेकिन मैं एक ऐसा चाहता था जो कई रूपों पर काम करे, और पहले से निर्दिष्ट कार्रवाई का उपयोग करें ताकि प्रत्येक फ़ाइल सही जगह पर जाए।

मैं jQuery के () विधि का उपयोग करना चाहता था ताकि मैं पहले से ही उपयोग करने से बच सकूं ()।

मुझे यह मिल गया है: (अपने jQuery चयनकर्ता के साथ formSelector को बदलें)

$(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.
    });

});

2

आजकल आपको jQuery :) fetch API सपोर्ट टेबल की भी आवश्यकता नहीं है

let result = fetch('url', {method: 'POST', body: new FormData(document.querySelector("#form"))})

फ़ाइल अपलोड के संदर्भ में fetchकृपया संगतता देखें: developer.mozilla.org/en-US/docs/Web/API/…
उमर तारिक

@OmarTariq हां, मेरे जवाब में एक समान लिंक है))
एलेक्स निकुलिन

उफ़। मुझे यह कैसे याद आ सकता है:-|
उमर तारिक

1

FormData वर्ग काम करता है, हालांकि iOS सफारी में (iPhone पर कम से कम) मैं राफेल स्कवीर्ट के समाधान का उपयोग करने में सक्षम नहीं था।

फॉर्मिलाटा ऑब्जेक्ट्स में हेरफेर करने पर मोज़िला देव का एक अच्छा पेज है ।

इसलिए, अपने पृष्ठ में कहीं एक खाली फ़ॉर्म जोड़ें, जो कि प्रतिरूप निर्दिष्ट कर रहा है:

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

फिर, फॉर्मडाटा ऑब्जेक्ट बनाएं:

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

और राफेल कोड में आगे बढ़ें ।


मैं अपने jquery ajax अपलोड के साथ एक समस्या को चुपचाप सफारी में लटका रहा था और एक ब्राउज़र सशर्त $ ('फॉर्म-नाम') कर रहा था। ajax अपलोड के बजाय Safari के लिए सबमिट करें () IE9 और FF18 में काम करता है। शायद बहु-अपलोड के लिए एक आदर्श समाधान नहीं है, लेकिन मैं एक एकल फ़ाइल के लिए एक jquery संवाद से एक iframe में ऐसा कर रहा था ताकि यह ठीक काम करे।
ग्लिफ़

1

एक गोच मैं आज भाग गया मुझे लगता है कि इस समस्या से संबंधित इंगित करने के लायक है: यदि अजाक्स कॉल के लिए यूआरएल को पुनर्निर्देशित किया गया है तो सामग्री-प्रकार के लिए शीर्षलेख: 'मल्टीपार्ट / फॉर्म-डेटा' खो सकता है।

उदाहरण के लिए, मैं http://server.com/context?param=x पर पोस्ट कर रहा था

Chrome के नेटवर्क टैब में मैंने इस अनुरोध के लिए सही मल्टीपार्ट हैडर देखा, लेकिन फिर http://server.com/context/?param=x पर 302 रीडायरेक्ट किया (संदर्भ के बाद स्लैश नोट करें)

रीडायरेक्ट के दौरान मल्टीपार्ट हेडर खो गया था। सुनिश्चित करें कि यदि ये समाधान आपके लिए काम नहीं कर रहे हैं, तो अनुरोधों को पुनर्निर्देशित नहीं किया जा रहा है।


1

ऊपर दिए गए सभी समाधान अच्छे और सुरुचिपूर्ण दिखते हैं, लेकिन फ़ॉर्मडेटा () ऑब्जेक्ट किसी भी पैरामीटर की अपेक्षा नहीं करता है, लेकिन इसे तुरंत भेजने के बाद परिशिष्ट () का उपयोग करें, जैसे कि ऊपर लिखे एक ने क्या लिखा है:

formData.append (val.name, val.value);


1

यदि फ़ाइल इनपुट nameएक सरणी और झंडे को इंगित करता है multiple, और आप पूरे के formसाथ पार्स करते हैं FormData, तो append()इनपुट फ़ाइलों को पुनरावृत्त करना आवश्यक नहीं है । FormDataस्वचालित रूप से कई फ़ाइलों को संभाल लेंगे।

$('#submit_1').on('click', function() {
  let data = new FormData($("#my_form")[0]);

  $.ajax({
    url: '/path/to/php_file',
    type: 'POST',
    data: data,
    processData: false,
    contentType: false,
    success: function(r) {
      console.log('success', r);
    },
    error: function(r) {
      console.log('error', r);
    }
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="my_form">
  <input type="file" name="multi_img_file[]" id="multi_img_file" accept=".gif,.jpg,.jpeg,.png,.svg" multiple="multiple" />
  <button type="button" name="submit_1" id="submit_1">Not type='submit'</button>
</form>

ध्यान दें कि एक नियमित button type="button"उपयोग किया जाता है, नहीं type="submit"। यह दिखाता है कि submitइस कार्यक्षमता को प्राप्त करने के लिए उपयोग पर कोई निर्भरता नहीं है।

$_FILESक्रोम देव टूल्स में परिणामी प्रविष्टि इस प्रकार है:

multi_img_file:
  error: (2) [0, 0]
  name: (2) ["pic1.jpg", "pic2.jpg"]
  size: (2) [1978036, 2446180]
  tmp_name: (2) ["/tmp/phphnrdPz", "/tmp/phpBrGSZN"]
  type: (2) ["image/jpeg", "image/jpeg"]

नोट: ऐसे मामले हैं जहां कुछ छवियां केवल एक फ़ाइल के रूप में अपलोड होने पर ठीक अपलोड होंगी, लेकिन कई फ़ाइलों के सेट में अपलोड किए जाने पर वे विफल हो जाएंगी। लक्षण यह है कि PHP खाली $_POSTऔर $_FILESबिना किसी त्रुटि के AJAX रिपोर्ट करता है । Chrome 75.0.3770.100 और PHP 7.0 के साथ समस्या होती है। केवल मेरे परीक्षण सेट में कई दर्जन छवियों में से 1 के साथ ऐसा लगता है।


0

IE के पुराने संस्करण FormData का समर्थन नहीं करते हैं (FormData के लिए पूर्ण ब्राउज़र समर्थन सूची यहां है: https://developer.mozilla.org/en-US/docs/Web/API/FormData )।

या तो आप jquery प्लगइन का उपयोग कर सकते हैं (उदाहरण के लिए, http://malsup.com/jquery/form/#code-samples ) या, आप ajax के माध्यम से मल्टीपार्ट फॉर्म डेटा पोस्ट करने के लिए IFrame आधारित समाधान का उपयोग कर सकते हैं: https: // developer। mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript


0

पीएचपी

<?php 
    var_dump( $_FILES ); 
?>

jQuery और प्रपत्र HTML

$( "#form" ).bind( "submit", function (e) {

    e.preventDefault();

    $.ajax({

        method: "post",
        url: "process.php",

        data: new FormData( $(this) ), // $(this) = formHTML element

        cache: false,

        /* upload */
        contentType: false,
        processData: false

    });

} )
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

<form id="form" >
    File: <input type="file" name="upload" />
    <input type="submit" value="Submit" />
</form>


-1
  1. jquery-> $ ("# आईडी") द्वारा फॉर्म ऑब्जेक्ट प्राप्त करें [0]
  2. डेटा = नया फॉर्मडाटा ($ ("# आईडी") [0]);
  3. ठीक है, डेटा आपकी इच्छा है

$ ("# id") [0] फॉर्म में से कोई भी पहले खाली <इनपुट प्रकार = "फ़ाइल" /> रिटर्न नहीं देता है, आप इसमें से सभी <इनपुट प्रकार = "फ़ाइल" /> सहित पूरे फॉर्म कैसे जमा करते हैं?
मोहम्मद-होसैन जमाली
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.