15

I'm trying to upload a file via ajax together with some fields in a form. However, it doesn't work. I get this error.

Undefined Index :- File

Here's my code.

HTML

<!-- File Button -->
<div class="form-group">
  <label class="col-md-4 control-label" for="file">Upload Software / File</label>
  
  <div class="col-md-4">
    <input id="file" name="file" class="input-file" type="file">
  </div>
</div>

<div class="form-group">
  <label class="col-md-4 control-label" for="price">Price($)</label>
  
  <div class="col-md-4">
    <input id="price" name="price" type="text" placeholder="Price" class="form-control input-md" required="">
  </div>
</div>

Ajax

$("#add_product").click(function(e) {
  e.preventDefault();
  product_name = $("product_name").val();
  //d = $("#add_new_product").serialize();
  
  $.ajax({
    type: 'POST',
    url: 'ajax.php',
    data: $("#add_new_product").serialize(),
    success: function(response) {
      //
      alert(response);

    }
  })
});

PHP

if (0 < $_FILES['file']['error']) {
  echo ":!";
} else {
  echo "ASa";
}

What am I missing here?

biberman
  • 5,606
  • 4
  • 11
  • 35
Akshay
  • 2,244
  • 3
  • 15
  • 34
  • Related: http://stackoverflow.com/questions/166221/how-can-i-upload-files-asynchronously/8758614#8758614 – Michael Doye Nov 17 '15 at 16:05
  • @M.Doye The problem here is, I have more data together with the file, which is causing the trouble. – Akshay Nov 17 '15 at 16:06
  • 1
    Serialize function will not include file in data variable there is another mechanism to achive this please google it. – siddhesh Nov 17 '15 at 16:07
  • You can use @M.Doye solution you have to trigger the code while submitting the form instead of file change event. – siddhesh Nov 17 '15 at 16:08
  • @siddhesh Could you possibly tell me that **mechanism name** ? – Akshay Nov 17 '15 at 16:12
  • 1
    check out this one it's perfectly matching your requirements. http://stackoverflow.com/questions/10899384/uploading-both-data-and-files-in-one-form-using-ajax – siddhesh Nov 17 '15 at 16:14

3 Answers3

14

Can you try using FormData():

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

The above is a sample code, but you may use it to modify it.

Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
11

you can use FormData

$("#add_product").click(function(e) {
  e.preventDefault();
  var fdata = new FormData()

  fdata.append("product_name", $("product_name").val());

  if ($("#file")[0].files.length > 0)
    fdata.append("file", $("#file")[0].files[0])
  //d = $("#add_new_product").serialize();
  $.ajax({
    type: 'POST',
    url: 'ajax.php',
    data: fdata,
    contentType: false,
    processData: false,
    success: function(response) {
      //
      alert(response);

    }
  })
});
<!-- File Button -->
<div class="form-group">
  <label class="col-md-4 control-label" for="file">Upload Software / File</label>
  
  <div class="col-md-4">
    <input id="file" name="file" class="input-file" type="file">
  </div>
</div>

<div class="form-group">
  <label class="col-md-4 control-label" for="price">Price($)</label>
  
  <div class="col-md-4">
    <input id="price" name="price" type="text" placeholder="Price" class="form-control input-md" required="">
  </div>
</div>
biberman
  • 5,606
  • 4
  • 11
  • 35
Suhail Keyjani
  • 488
  • 3
  • 10
9

We need to acknowledge first is that we need to APPEND both Form Input Data and Form File(s) into a single FormData variable.

Here is my solution in which I have enabled Multi File option so that this solution can fit for all examples.

It is Important to include name attribute in the input controls to make it work properly on server side in most of cases. If you are using C# then you can use simply Request.Form["nameAttribute"] to simply get the function. It is similar for Java and other languages.

My Sample Code is

   $(document).ready(function () //Setting up on Document to Ready Function
    {
        $("#btnUpload").click(function (event) {

            //getting form into Jquery Wrapper Instance to enable JQuery Functions on form                    
            var form = $("#myForm1");

            //Serializing all For Input Values (not files!) in an Array Collection so that we can iterate this collection later.
            var params = form.serializeArray();

            //Getting Files Collection
            var files = $("#File1")[0].files;

            //Declaring new Form Data Instance  
            var formData = new FormData();

            //Looping through uploaded files collection in case there is a Multi File Upload. This also works for single i.e simply remove MULTIPLE attribute from file control in HTML.  
            for (var i = 0; i < files.length; i++) {
                formData.append(files[i].name, files[i]);
            }
            //Now Looping the parameters for all form input fields and assigning them as Name Value pairs. 
            $(params).each(function (index, element) {
                formData.append(element.name, element.value);
            });

            //disabling Submit Button so that user cannot press Submit Multiple times
            var btn = $(this);
            btn.val("Uploading...");
            btn.prop("disabled", true);

            $.ajax({
                url: "Handler.ashx", //You can replace this with MVC/WebAPI/PHP/Java etc
                method: "post",
                data: formData,
                contentType: false,
                processData: false,
                success: function () {
                    //Firing event if File Upload is completed!  
                    alert("Upload Completed");
                    btn.prop("disabled", false);
                    btn.val("Submit");
                    $("#File1").val("");

                },
                error: function (error) { alert("Error"); }

            });

        });

    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form enctype="multipart/form-data" method="post" id="myForm1">
    <p><textarea id="TextArea1" rows="2" cols="20" name="TextArea1"></textarea></p>
    <p><input id="File1" type="file" multiple="multiple" /></p>
    <input id="btnUpload" type="button" value="Submit" />
    </form>

For a working example (asp.net C# with handlers) you can visit sample code on https://github.com/vibs2006/HttpFileHandlerFormDataSample

vibs2006
  • 6,028
  • 3
  • 40
  • 40
  • Running code snippet gives me this `From an Embedded Page at stacksnippets.net Error`. Why? – Tan Apr 08 '18 at 05:15
  • @Tan thats happening because Server side like that of 'Handler.ashx' cannot be executed under snippet.WHy don't u try the same at your localhost using my github code. – vibs2006 Apr 08 '18 at 07:41
  • Can you share your github code that you are referring to? I mean without ASP.NET/C# thing. – Tan Apr 09 '18 at 17:05
  • @Tan its already present in the last line of my post. https://github.com/vibs2006/HttpFileHandlerFormDataSample – vibs2006 Apr 10 '18 at 07:36
  • 1
    One more link https://qawithexperts.com/questions/301/how-to-do-javascript-file-upload – vibs2006 Jun 05 '18 at 10:17
  • @prateekkathal Thank you for this script. It is almost exactly what I am looking for. Is there anyway to use the success: function () { to redirect users to a thank you page? – 5150 Design Sep 26 '18 at 17:17
  • @5150Design Yes it is very easy. Simply use `window.location.href = "http://your.thank.you.url.com"` in end of your `success` function. – vibs2006 Sep 27 '18 at 06:39
  • @vibs2006 Thank you! – 5150 Design Sep 27 '18 at 12:05
  • @vibs2006 Any way to ensure that 'required' fields are checked prior to upload? – 5150 Design Sep 27 '18 at 12:51
  • @5150-Design pl check https://jqueryvalidation.org/ for all production level validation solutions – vibs2006 Sep 27 '18 at 17:19