248

This is my HTML which I'm generating dynamically using drag and drop functionality.

<form method="POST" id="contact" name="13" class="form-horizontal wpc_contact" novalidate="novalidate" enctype="multipart/form-data">
<fieldset>
    <div id="legend" class="">
        <legend class="">file demoe 1</legend>
        <div id="alert-message" class="alert hidden"></div>
    </div>

    <div class="control-group">
        <!-- Text input-->
        <label class="control-label" for="input01">Text input</label>
        <div class="controls">
            <input type="text" placeholder="placeholder" class="input-xlarge" name="name">
            <p class="help-block" style="display:none;">text_input</p>
        </div>
        <div class="control-group">  </div>
        <label class="control-label">File Button</label>

        <!-- File Upload --> 
        <div class="controls">
            <input class="input-file" id="fileInput" type="file" name="file">
        </div>
    </div>
    <div class="control-group">    

        <!-- Button --> 
        <div class="controls">
            <button class="btn btn-success">Button</button>
        </div>
    </div>
</fieldset>
</form> 

This is my JavaScript code:

<script>
    $('.wpc_contact').submit(function(event){
        var formname = $('.wpc_contact').attr('name');
        var form = $('.wpc_contact').serialize();               
        var FormData = new FormData($(form)[1]);

        $.ajax({
            url : '<?php echo plugins_url(); ?>'+'/wpc-contact-form/resources/js/tinymce.php',
            data : {form:form,formname:formname,ipadd:ipadd,FormData:FormData},
            type : 'POST',
            processData: false,
            contentType: false,
            success : function(data){
            alert(data); 
            }
        });
   }
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
Kalpit
  • 4,556
  • 4
  • 22
  • 43
  • 2
    You should read this (https://developer.mozilla.org/en-US/docs/Web/API/FormData/append) the `formData();` append method has an optional third parameter for a file. – www139 Dec 26 '15 at 14:36

9 Answers9

524

For correct form data usage you need to do 2 steps.

Preparations

You can give your whole form to FormData() for processing

var form = $('form')[0]; // You need to use standard javascript object here
var formData = new FormData(form);

or specify exact data for FormData()

var formData = new FormData();
formData.append('section', 'general');
formData.append('action', 'previewImg');
// Attach file
formData.append('image', $('input[type=file]')[0].files[0]); 

Sending form

Ajax request with jquery will looks like this:

$.ajax({
    url: 'Your url here',
    data: formData,
    type: 'POST',
    contentType: false, // NEEDED, DON'T OMIT THIS (requires jQuery 1.6+)
    processData: false, // NEEDED, DON'T OMIT THIS
    // ... Other options like success and etc
});

After this it will send ajax request like you submit regular form with enctype="multipart/form-data"

Update: This request cannot work without type:"POST" in options since all files must be sent via POST request.

Note: contentType: false only available from jQuery 1.6 onwards

Community
  • 1
  • 1
Spell
  • 6,696
  • 1
  • 14
  • 19
  • 1
    Can I set the "enctype" in the Ajax call? I think I may have an issue with it. Or, can I set it on the FormData object? – Wouter Jun 01 '14 at 07:50
  • You can. For this see lines after THIS MUST BE DONE FOR FILE UPLOADING in my code. – Spell Jun 02 '14 at 12:37
  • 1
    @Spell How get data in controller? Do need send `getCsrfToken`? –  Юрий Светлов May 22 '16 at 16:11
  • @ЮрийСветлов This is depends of what type of controller you use. Is it server side or front side controller? You trying to solve CSRF protection here? – Spell Aug 08 '16 at 10:43
  • How are the file contents actually read? The contents are not in the event object from the File Input. Is the FileReader being used invisibly in the background? – Simon H Oct 18 '16 at 18:55
  • That is browser side question. You give one internal object into another. And when you send request, formdata converts from js object to http formatted request – Spell Oct 18 '16 at 19:35
  • Can you add more stuff to the $_FILES elements? a "file" entry has some basic info, like `name`, `tmp_name` etc - can you add more? I ended up using $_POST. – Buffalo May 15 '17 at 12:09
  • @Buffalo `$_FILES` array generates by php server. You cannot change it outside of your script. All you can do - you can upload as many files as server accepts and it will filled for your server script in `$_FILES`. If you want to add some other staff - you need to use `$_GET` or `$_POST` data – Spell May 19 '17 at 08:05
  • Yeah, I saw that :( it's kind of lame. – Buffalo May 19 '17 at 10:50
  • If you need to get the form by id, i.e. $('#formid'), you need to use $('#formid')[0]. Ex: var formData = new FormData($('#formid')[0]); – Envayo Sep 30 '17 at 15:32
  • Yup. Or any other jquery support type of ids. eg: `$('div#parent_block_id form[name=form_name]')` – Spell Oct 04 '17 at 09:19
  • `var form = $('form')[0]; // You need to use standard javascript object here var formData = new FormData(form);` gives me a null value even on the browser any ideas? – Paulo Mar 29 '18 at 07:51
  • @Paulo probably some problems with selector? – Spell Jun 18 '18 at 15:50
  • Why do we need to use `var form = $('form')[0];` why not use `var form = $('form');` ? I get it that `$('form')[0];` gives me the complete HTML form but why is it needed? – Manthan Jamdagni Oct 21 '18 at 17:04
  • 2
    @ManthanJamdagni When you get `$('form')`, it will return jQuery object. But we need regular js object here without jQuery functionality. That's why we get regular object with `[0]` notation. Instead of this construction you can call `document.getElementById()` or simular call. – Spell Oct 22 '18 at 08:31
  • Why `new FormData(form);` returns an empty object inspite my form having many input fields with values? – van_folmert Jan 29 '19 at 14:10
  • @van_folmert it isn't actually empty. You can call ::get() or ::getAll() with a key parameter and it will return the value from the form. It looks like empty because it is an internal browser functionality. Here i show how to make a ajax call with a custom inputs. – Spell Feb 14 '19 at 12:27
  • Regarding "all files must be sent via POST request": Can HTTP PUT be used instead of POST? – Jon Schneider May 02 '19 at 20:12
  • What are the `'section'` and `'action'` lines for? Are those required? (They don't seem to correspond to anything in the OP?) – Jon Schneider May 02 '19 at 20:20
  • I used it and I have some problems when I use it on mobile chrome browsers with Android. Any solution? – hillcode Oct 21 '19 at 19:46
  • I'm trying this solution, but have server issues. Server side PHP-script, which handles the upload, has `$_FILES` array always empty. What could be a reason? – userlond Nov 21 '19 at 09:37
  • Issue was jQuery version, it was too old. Thanks for metioned this in answer! – userlond Nov 21 '19 at 09:45
  • this worked great, except that I am not getting a response from the request. anyone know why? – Dimitri Bostrovich May 04 '20 at 22:43
  • @hillcode did you find a solution? – Crashalot Jan 06 '21 at 02:11
41

I can't add a comment above as I do not have enough reputation, but the above answer was nearly perfect for me, except I had to add

type: "POST"

to the .ajax call. I was scratching my head for a few minutes trying to figure out what I had done wrong, that's all it needed and works a treat. So this is the whole snippet:

Full credit to the answer above me, this is just a small tweak to that. This is just in case anyone else gets stuck and can't see the obvious.

  $.ajax({
    url: 'Your url here',
    data: formData,
    type: "POST", //ADDED THIS LINE
    // THIS MUST BE DONE FOR FILE UPLOADING
    contentType: false,
    processData: false,
    // ... Other options like success and etc
})
Community
  • 1
  • 1
supertemp
  • 582
  • 4
  • 11
23
<form id="upload_form" enctype="multipart/form-data">

jQuery with CodeIgniter file upload:

var formData = new FormData($('#upload_form')[0]);

formData.append('tax_file', $('input[type=file]')[0].files[0]);

$.ajax({
    type: "POST",
    url: base_url + "member/upload/",
    data: formData,
    //use contentType, processData for sure.
    contentType: false,
    processData: false,
    beforeSend: function() {
        $('.modal .ajax_data').prepend('<img src="' +
            base_url +
            '"asset/images/ajax-loader.gif" />');
        //$(".modal .ajax_data").html("<pre>Hold on...</pre>");
        $(".modal").modal("show");
    },
    success: function(msg) {
        $(".modal .ajax_data").html("<pre>" + msg +
            "</pre>");
        $('#close').hide();
    },
    error: function() {
        $(".modal .ajax_data").html(
            "<pre>Sorry! Couldn't process your request.</pre>"
        ); // 
        $('#done').hide();
    }
});

you can use.

var form = $('form')[0]; 
var formData = new FormData(form);     
formData.append('tax_file', $('input[type=file]')[0].files[0]);

or

var formData = new FormData($('#upload_form')[0]);
formData.append('tax_file', $('input[type=file]')[0].files[0]); 

Both will work.

Quentin
  • 800,325
  • 104
  • 1,079
  • 1,205
chandoo
  • 1,056
  • 1
  • 16
  • 25
1
$(document).ready(function () {
    $(".submit_btn").click(function (event) {
        event.preventDefault();
        var form = $('#fileUploadForm')[0];
        var data = new FormData(form);
        data.append("CustomField", "This is some extra data, testing");
        $("#btnSubmit").prop("disabled", true);
        $.ajax({
            type: "POST",
            enctype: 'multipart/form-data',
            url: "upload.php",
            data: data,
            processData: false,
            contentType: false,
            cache: false,
            timeout: 600000,
            success: function (data) {
                console.log();
            },
        });
    });
});
1

Better to use the native javascript to find the element by id like: document.getElementById("yourFormElementID").

$.ajax( {
      url: "http://yourlocationtopost/",
      type: 'POST',
      data: new FormData(document.getElementById("yourFormElementID")),
      processData: false,
      contentType: false
    } ).done(function(d) {
           console.log('done');
    });
Ranch Camal
  • 306
  • 3
  • 10
0
View:
<label class="btn btn-info btn-file">
Import <input type="file" style="display: none;">
</label>
<Script>
$(document).ready(function () {
                $(document).on('change', ':file', function () {
                    var fileUpload = $(this).get(0);
                    var files = fileUpload.files;
                    var bid = 0;
                    if (files.length != 0) {
                        var data = new FormData();
                        for (var i = 0; i < files.length ; i++) {
                            data.append(files[i].name, files[i]);
                        }
                        $.ajax({
                            xhr: function () {
                                var xhr = $.ajaxSettings.xhr();
                                xhr.upload.onprogress = function (e) {
                                    console.log(Math.floor(e.loaded / e.total * 100) + '%');
                                };
                                return xhr;
                            },
                            contentType: false,
                            processData: false,
                            type: 'POST',
                            data: data,
                            url: '/ControllerX/' + bid,
                            success: function (response) {
                                location.href = 'xxx/Index/';
                            }
                        });
                    }
                });
            });
</Script>
Controller:
[HttpPost]
        public ActionResult ControllerX(string id)
        {
            var files = Request.Form.Files;
...
Vkl125
  • 120
  • 1
  • 9
0
$('#form-withdraw').submit(function(event) {

    //prevent the form from submitting by default
    event.preventDefault();



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

    $.ajax({
        url: 'function/ajax/topup.php',
        type: 'POST',
        data: formData,
        async: false,
        cache: false,
        contentType: false,
        processData: false,
        success: function (returndata) {
          if(returndata == 'success')
          {
            swal({
              title: "Great",
              text: "Your Form has Been Transfer, We will comfirm the amount you reload in 3 hours",
              type: "success",
              showCancelButton: false,
              confirmButtonColor: "#DD6B55",
              confirmButtonText: "OK",
              closeOnConfirm: false
            },
            function(){
              window.location.href = '/transaction.php';
            });
          }

          else if(returndata == 'Offline')
          {
              sweetAlert("Offline", "Please use other payment method", "error");
          }
        }
    });



}); 
0

Actually The documentation shows that you can use XMLHttpRequest().send() to simply send multiform data in case jquery sucks

Ved Prakash
  • 1,390
  • 5
  • 22
  • 31
Richie
  • 401
  • 5
  • 7
-7

Good morning.

I was have the same problem with upload of multiple images. Solution was more simple than I had imagined: include [] in the name field.

<input type="file" name="files[]" multiple>

I did not make any modification on FormData.

E. Coelho
  • 1
  • 2
  • 1
    This has nothing to do with the problem the question is asking about and is just a peculiarity of how PHP handles form data with multiple values that have the same name. – Quentin Apr 24 '19 at 15:17