Ajax kullanarak veri ve dosyaları tek bir formda mı yüklüyorsunuz?


384

Veri ve dosya göndermek için formlarım için jQuery ve Ajax kullanıyorum ama nasıl veri ve dosyaları tek bir formda göndermek için emin değilim?

Şu anda her iki yöntemle hemen hemen aynı şeyi yapıyorum, ancak verilerin bir diziye toplanma şekli farklı, verileri kullanıyor .serialize();ancak dosyaları kullanıyor= new FormData($(this)[0]);

Ajax aracılığıyla dosya ve verileri tek bir biçimde yükleyebilmek için her iki yöntemi de birleştirmek mümkün müdür?

Veri jQuery, Ajax ve html

$("form#data").submit(function(){

    var formData = $(this).serialize();

    $.ajax({
        url: window.location.pathname,
        type: 'POST',
        data: formData,
        async: false,
        success: function (data) {
            alert(data)
        },
        cache: false,
        contentType: false,
        processData: false
    });

    return false;
});

<form id="data" method="post">
    <input type="text" name="first" value="Bob" />
    <input type="text" name="middle" value="James" />
    <input type="text" name="last" value="Smith" />
    <button>Submit</button>
</form>

JQuery, Ajax ve html dosyaları

$("form#files").submit(function(){

    var formData = new FormData($(this)[0]);

    $.ajax({
        url: window.location.pathname,
        type: 'POST',
        data: formData,
        async: false,
        success: function (data) {
            alert(data)
        },
        cache: false,
        contentType: false,
        processData: false
    });

    return false;
});

<form id="files" method="post" enctype="multipart/form-data">
    <input name="image" type="file" />
    <button>Submit</button>
</form>

Ajax aracılığıyla veri ve dosyaları tek bir formda gönderebilmek için yukarıdakileri nasıl birleştirebilirim?

Amacım Ajax ile tüm bu formları tek bir gönderiye gönderebilmek mümkün mü?

<form id="datafiles" method="post" enctype="multipart/form-data">
    <input type="text" name="first" value="Bob" />
    <input type="text" name="middle" value="James" />
    <input type="text" name="last" value="Smith" />
    <input name="image" type="file" />
    <button>Submit</button>
</form>

2
FormDataYaklaşım, sadece dosya yükleme alanları istersen ihtiva formlarla cezası çalışmalıdır; yine de geniş çapta desteklenmemektedir.
lanzz

@lanzz hangisi? serialize olan biri sadece veri için çalışıyor gibi görünüyor, ama diğeri sadece dosyalar için çalışıyor gibi görünüyor?
Dan

Bu MDN sayfasına bakıldığında , kullandığınızda tüm form verileri gönderilmelidirFormData
lanzz

1
@lanzz haklısınız, yanlış form kimliğini kullanmam gerektiğini düşündüğüm şekilde çalışıyor, ajax ile tek bir form üzerinden hem dosyaları hem de verileri yükleyebilirsiniz.
Dan

Çoklu seçim dosya girişi olduğunda bu işe yaramıyor gibi görünüyor. Yalnızca ilk dosyayı yükler.
Sami Al-Subhi

Yanıtlar:


458

Sahip olduğum sorun yanlış jQuery tanımlayıcı kullanmak oldu.

Sen veri ve dosya yükleyebilir tek biçim ile ajax kullanarak .

PHP + HTML

<?php

print_r($_POST);
print_r($_FILES);
?>

<form id="data" method="post" enctype="multipart/form-data">
    <input type="text" name="first" value="Bob" />
    <input type="text" name="middle" value="James" />
    <input type="text" name="last" value="Smith" />
    <input name="image" type="file" />
    <button>Submit</button>
</form>

jQuery + Ajax

$("form#data").submit(function(e) {
    e.preventDefault();    
    var formData = new FormData(this);

    $.ajax({
        url: window.location.pathname,
        type: 'POST',
        data: formData,
        success: function (data) {
            alert(data)
        },
        cache: false,
        contentType: false,
        processData: false
    });
});

Kısa versiyon

$("form#data").submit(function(e) {
    e.preventDefault();
    var formData = new FormData(this);    

    $.post($(this).attr("action"), formData, function(data) {
        alert(data);
    });
});

17
IE <10 sürümlerinde bu çözüm çalışmaz, çünkü FormData IE 8 veya 9'da bulunmayan bir HTML5 nesnesidir.
Xavier Guzman

34
$(this)[0]sadece bir takma addır this, bu yüzden new FormData(this)yeterli olmalıdır.
r3wt

9
FormData nesnesini incelemek mümkün görünmüyor, bu soruya bakın (Nesne her zaman boş olduğu için benimle aynı cluelessness çalışan herkes için).
Laura

28
Gelecekteki okuyucular için: contentType ve processData bildirimleri önemlidir. Daha fazla bilgi için bu cevaba bakınız .
AaronSieb

5
bunun async: falseçalışması için gerekli görünmüyor ve mobil (tek iş parçacıklı) tarayıcılarda engellemeye neden oluyor
Jeremy

33

diğer bir seçenek de iframe kullanmak ve formun hedefini ona ayarlamaktır.

bunu deneyebilirsiniz (jQuery kullanır):

function ajax_form($form, on_complete)
{
    var iframe;

    if (!$form.attr('target'))
    {
        //create a unique iframe for the form
        iframe = $("<iframe></iframe>").attr('name', 'ajax_form_' + Math.floor(Math.random() * 999999)).hide().appendTo($('body'));
        $form.attr('target', iframe.attr('name'));
    }

    if (on_complete)
    {
        iframe = iframe || $('iframe[name="' + $form.attr('target') + '"]');
        iframe.load(function ()
        {
            //get the server response
            var response = iframe.contents().find('body').text();
            on_complete(response);
        });
    }
}

tüm tarayıcılarda iyi çalışır, verileri serileştirmenize veya hazırlamanıza gerek yoktur. aşağı tarafı ise ilerlemeyi izleyememenizdir.

ayrıca, en azından krom için, istek geliştirici araçlarının "xhr" sekmesinde değil, "doc" altında görünür


1
Aslında Ajax değil, aynı soruya sahip insanlar için hala yararlı olabilir.
Roey

3
Neden bu cevabın -2 aldığına inanamıyorum, eski tarayıcı desteğine ihtiyacım olduğu için bunu kullandım
Sijav

Diğer yanıtlar 'eski tarayıcılar çalışmıyor' veya 'iframe kesmek kullanılabilir' ama hiçbir zaman bunları ele almadığından, bu yanıt iş parçacığında olmalıdır. Güzel kod parçası, ayrıca onload doğru şekilde nasıl kullanılacağını gösteren +1
mschr

18

ASPT MVC HttpPostedFilebase ile aynı sorunu yaşıyordum ve Gönder üzerinde form kullanmak yerine Ben bazı şeyler yapmak için gerekli tıklayın düğmesini kullanmak gerekiyordu ve sonra tüm Tamam gönderme formu yani burada nasıl çalıştığını

$(".submitbtn").on("click", function(e) {

    var form = $("#Form");

    // you can't pass Jquery form it has to be javascript form object
    var formData = new FormData(form[0]);

    //if you only need to upload files then 
    //Grab the File upload control and append each file manually to FormData
    //var files = form.find("#fileupload")[0].files;

    //$.each(files, function() {
    //  var file = $(this);
    //  formData.append(file[0].name, file[0]);
    //});

    if ($(form).valid()) {
        $.ajax({
            type: "POST",
            url: $(form).prop("action"),
            //dataType: 'json', //not sure but works for me without this
            data: formData,
            contentType: false, //this is requireded please see answers above
            processData: false, //this is requireded please see answers above
            //cache: false, //not sure but works for me without this
            error   : ErrorHandler,
            success : successHandler
        });
    }
});

Bu, MVC modelinizi doğru bir şekilde dolduracak, lütfen Modelinizde, HttpPostedFileBase [] Özelliğinin html'deki giriş denetiminin Adı ile aynı ada sahip olduğundan emin olun.

<input id="fileupload" type="file" name="UploadedFiles" multiple>

public class MyViewModel
{
    public HttpPostedFileBase[] UploadedFiles { get; set; }
}

1
Zaman kazandırıcısınız. :)
Suhail Mumtaz Awan

Benim durumumda kullanmak zorunda kaldım:contentType : "application/octet-stream"
Christophe Roussy

Sağol kanka! Çok zaman kazandın.
Erişim Reddedildi

Django ile çalışıyor, güzel!
csandreas1

Teşekkürler dostum! Aşağıdaki 2 satır benim için çalıştı. var form = $ ("# Form"); var formData = yeni FormData (form [0]);
Rajiv Kumar

15

Veya daha kısa:

$("form#data").submit(function() {
    var formData = new FormData(this);
    $.post($(this).attr("action"), formData, function() {
        // success    
    });
    return false;
});

bu şekilde, aynı komut dosyasını kullanarak bir veri alanını nasıl doğrularsınız, yani formunuzda bir metin alanınız ve bir dosya alanınız varsa
George

6

Benim enctype: 'multipart/form-data'için Ajax isteğinde alan olmadan çalışmadı . Umarım benzer bir problemde sıkışmış birine yardımcı olur.

enctype Form özniteliğinde zaten ayarlanmış olsa da , bazı nedenlerden dolayı Ajax isteği, enctypeaçık bildirim olmadan otomatik olarak tanımlamadı (jQuery 3.3.1).

// Tested, this works for me (jQuery 3.3.1)

fileUploadForm.submit(function (e) {   
    e.preventDefault();
    $.ajax({
            type: 'POST',
            url: $(this).attr('action'),
            enctype: 'multipart/form-data',
            data: new FormData(this),
            processData: false,
            contentType: false,
            success: function (data) {
                console.log('Thank God it worked!');
            }
        }
    );
});

// enctype field was set in the form but Ajax request didn't set it by default.

<form action="process/file-upload" enctype="multipart/form-data" method="post" >

     <input type="file" name="input-file" accept="text/plain" required> 
     ...
</form>

Yukarıda belirtildiği gibi, contentTypeve processDataalanlarına da özellikle dikkat edin .


1
"Benim için, Ajax isteğinde 'multipart / form-data' alanı şifreleme olmadan çalışmadı." - Bunun bir etkisi olamaz. JQuery.ajax tarafından tanınan bir özellik değildir. Bkz belgelereenctype hiç söz edilmez.
Quentin

Daha önce de belirttiğim gibi, birden fazla farklı cevap denedim ama işe yaramadılar. JS konsolunda kodlama hatasını belirten bir Ajax hatası gösterildi. Daha sonra nihayet benim kod çalışması yapan bu öğretici takip ve ben burada yayınlanmıştır. Belki de enctypealan bir nedenden dolayı dokümantasyonda yer almamaktadır. Kesinlikle söyleyemem jQuery kaynak kodunu kontrol etmedim.
Adithya Upadhya

"Belki de şifreleme alanı bir nedenden ötürü belgelerde yer almıyor." - Bu nedenle jQuery onunla hiçbir şey yapmaz, bu yüzden saçmalıktır.
Quentin

Belki de Mkyong ile iletişime geçebilir ve onunla konuşabilirsiniz. enctypeAlanı kaldırarak kodumu tekrar test ettim ve artık dosyaları yüklemiyor (kodlama türü hata döndürüyor). Ben jQuery kaynak kodunu kontrol etmedi beri nasıl çalışır emin değilim. Bu cevabı, benzer bir soruna takılan başkalarına yardım etmek amacıyla gönderdim. Burada oy için balık tutmuyorum ... Başka sorularınız / yorumlarınız varsa, yorum yapmak yerine sohbet edelim.
Adithya Upadhya

1

Kod çalışmasını takip etmek benim için

$(function () {
    debugger;
    document.getElementById("FormId").addEventListener("submit", function (e) {
        debugger;
        if (ValidDateFrom()) { // Check Validation 
            var form = e.target;
            if (form.getAttribute("enctype") === "multipart/form-data") {
                debugger;
                if (form.dataset.ajax) {
                    e.preventDefault();
                    e.stopImmediatePropagation();
                    var xhr = new XMLHttpRequest();
                    xhr.open(form.method, form.action);
                    xhr.onreadystatechange = function (result) {
                        debugger;
                        if (xhr.readyState == 4 && xhr.status == 200) {
                            debugger;
                            var responseData = JSON.parse(xhr.responseText);
                            SuccessMethod(responseData); // Redirect to your Success method 
                        }
                    };
                    xhr.send(new FormData(form));
                }
            }
        }
    }, true);
});

Eylem Sonrası Yöntemi'nde, parametreyi HttpPostedFileBase UploadFile olarak iletin ve dosya girişinizin Eylem Yöntemi parametrenizde belirtilenle aynı olduğundan emin olun. AJAX Begin formuyla da çalışmalıdır.

Burada, yukarıda belirtilen kodda tanımlanmış çağrıyı yaptığınızdan ve Gereksinim uyarınca koddaki yönteminize başvurabileceğiniz için AJAX BEGIN Formunuzun burada çalışmadığını unutmayın.

Geç cevap verdiğimi biliyorum ama bu benim için işe yaradı


1

Basit ama daha etkili bir yol:
new FormData()kendisi bir konteyner (veya bir çanta) gibidir. Her şeyi attr veya dosyaya koyabilirsiniz. attribute, file, fileNameÖrneğin eklemeniz gereken tek şey :

let formData = new FormData()
formData.append('input', input.files[0], input.files[0].name)

ve sadece AJAX isteğinde iletin. Örneğin:

    let formData = new FormData()
    var d = $('#fileid')[0].files[0]

    formData.append('fileid', d);
    formData.append('inputname', value);

    $.ajax({
        url: '/yourroute',
        method: 'POST',
        contentType: false,
        processData: false,
        data: formData,
        success: function(res){
            console.log('successfully')
        },
        error: function(){
            console.log('error')
        }
    })

FormData ile n sayıda dosya veya veri ekleyebilirsiniz.

ve Script.js dosyasından Node.js dosyasında Route dosyasına AJAX İsteği yapıyorsanız , dosyaya (ör. resim, video vb.)
req.bodyerişmek için verilere (örn. metin) erişmek için kullanmaya dikkat edin.
req.files


-1

Benim durumumda, başlık aracılığıyla gönderilen bilgileri ve ayrıca bir FormData nesnesi kullanılarak gönderilen bir dosya vardı bir POST isteği yapmak zorunda kaldı.

Buradaki bazı cevapların bir kombinasyonunu kullanarak çalıştım, bu yüzden temelde çalışmanın sonunda Ajax isteğimde bu beş satır vardı:

 contentType: "application/octet-stream",
 enctype: 'multipart/form-data',
 contentType: false,
 processData: false,
 data: formData,

Burada formData şöyle bir değişken oluşturdu:

 var file = document.getElementById('uploadedFile').files[0];
 var form = $('form')[0];
 var formData = new FormData(form);
 formData.append("File", file);

1
contentType: "application/octet-stream",aktif olarak zararlıdır ve bir soruna neden olmamasının tek nedeni, daha sonra iki satırın üzerine yazmanızdır.
Quentin

1
enctype: 'multipart/form-data',anlamsız. jQuery.ajax bu parametreyi tanımıyor.
Quentin

… Cevabınızın geri kalanı soru başlığındaki "veri ve dosyaların" "veri" bitini karşılayamıyor .
Quentin

-2
<form id="form" method="post" action="otherpage.php" enctype="multipart/form-data">
    <input type="text" name="first" value="Bob" />
    <input type="text" name="middle" value="James" />
    <input type="text" name="last" value="Smith" />
    <input name="image" type="file" />
    <button type='button' id='submit_btn'>Submit</button>
</form>

<script>
$(document).on("click", "#submit_btn", function (e) {
    //Prevent Instant Click  
    e.preventDefault();
    // Create an FormData object 
    var formData = $("#form").submit(function (e) {
        return;
    });
    //formData[0] contain form data only 
    // You can directly make object via using form id but it require all ajax operation inside $("form").submit(<!-- Ajax Here   -->)
    var formData = new FormData(formData[0]);
    $.ajax({
        url: $('#form').attr('action'),
        type: 'POST',
        data: formData,
        success: function (response) {
            console.log(response);
        },
        contentType: false,
        processData: false,
        cache: false
    });
    return false;
});
</script>

///// otherpage.php

<?php
    print_r($_FILES);
?>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.