1

I am having a problem with sending a form with both text and file fields. I can choose from :

1) sending customized request with specified fields

$("#form_new_product").submit(function(event){
event.preventDefault();
    if ( product_name ) { 
        $.post( 
            '/product/create',
            { product_name: product_name,
              product_description: product_description
              // file : file ???
            })  
        .fail(function(res){
            alert("Error: " + res.getResponseHeader("error"));
            })  
        .done(function(res){
            showInfoAlert("Product : \"" + product_name + "\" has been added to catalog.");
            }); 
    }
}

but this way I cannot specify the file (file.path) to be uploaded - that's what being passed with files field of POST request (any idea how to do it ?)

2) post the 'normal'/not customized form fields but I am not sure how to do it with ajax in jquery (to use methods from above snippet showInfoAlert and showErrorAlert to indicate response status)

Patryk
  • 22,602
  • 44
  • 128
  • 244

3 Answers3

2

An excellent way to handle this, since you're using jQuery anyway, is the jQuery Form plugin: http://malsup.com/jquery/form/. It's widely used, free of any major bugs as far as I've ever seen (been using it for many months), easy to implement.

Steve Schneider
  • 392
  • 2
  • 5
  • It looks nice but I cannot understand how can I join text and file fields to put in one POST request. – Patryk Jan 26 '14 at 23:03
  • @Patryk just add more `` next to the file input, or before, in the same form, with this plugin you can just `$('#form_new_product').ajaxSubmit({success: ..., error: ...})` and it will submit ALL the fields, the text and file types as well. see my answer below for an example – bentael Jan 27 '14 at 05:52
  • It didn't answer the question – Saeed Ansari Mar 25 '16 at 12:07
1

First off, make sure you name your form inputs correctly, that will make your life easier

If you do not wish to support IE8/9 for your ajax upload you can use the following:

// FormData is not supported by ie8 and 9 as far as I know
// and some others see here: http://caniuse.com/#search=FormData 
// you can check for FormData support by something like this
var supportFormData = function(){
    return !! window.FormData;
};

 $('#form_new_product').submit(function(e) {
    e.preventDefault();
    var form;

    // you can pass in your form element here if you have the <input> tags named correctly, like this:
    form = new FormData($("#form_new_product").eq(0)) // that's the easiest way

    // or you can create a FormData object and append stuff to it
    form = new FormData();
    // signature --> form.append(input[name], input[value])
    form.append('product_name', $('#form_new_product input[name="product_name"]').val());
    form.append('product_description', $('#form_new_productinput[name="product_description"]').val());
    // now a file input,
    form.append('product_image', $('#form_new_product input[type="file"]').eq(0).files[0], 'image.png'/*optional*/);

    return $.ajax({
        url: '/path/to/form/action',
        type: 'POST',
        data: form,
        mimeType:'multipart/form-data",
        contentType: false,
        cache: false,
        processData: false
    )
    .done(function(response){
       // handle success
    })
    .fail(function(response){
       // handle error
    });
});

If you want to support IE8 and IE9, you may need to do some little tweaking server side as well, and your submitForm function won't be as simple as the previous one, I would suggest using http://malsup.com/jquery/form/ like some of the other answers did, but as the plugin mentions, here the server response header MUST be text/html so IE8 won't trigger a file download for a JSON response (assuming you are expecting a JSON response) - basically this plugin is creating an iFrame with a form in it and submits it to the server for you. There is other solution than the text/html like wrapping the response with a <textarea>, check that last link I mentioned.

So, assuming you are using this plugin, here's I would do it.

var isIE = function () {
    var myNav = navigator.userAgent.toLowerCase();
    return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
}

$('#form_new_product').submit(function(e) {
    e.preventDefault();
    var $form = $("#form_new_product");

    var options = {
        url: '/path/to/form/action',
        type: "POST",
        mimeType: "multipart/form-data"
    };

    // hack because IE lt 9 iFrame triggers a file download for a application/json response
    // http://stackoverflow.com/questions/17701992/ie-iframe-doesnt-handle-application-json-response-properly
    if (Reporting.util.isIE() <= 9) {
        // maybe you have another contract with the server, like a custom query string or whatever
        // but the server needs to return text/html
        options.ContentType = "text/html";
    }

    // don't think this returns a promise, so you can use the options.success and options.error like that
    options.success = function(response){
      // handle success
    };
    options.error = function(response){
      // handle error
    };

    // or you really want to return a promise, then you can 
    var deferred = new $.Deferred();
    options.success(function(response){
        deferred.resolve(response);
    });
    options.error(function(response){
        deferred.reject(response);
    })

        // this will submit all of your inputs
    form.ajaxSubmit(options);
    return deferred;
});                                                                      
bentael
  • 1,987
  • 2
  • 21
  • 27
-1

You can't send file field without user's confirmation. User has to fill the field by hand.

If it's ok for you, you can read this page which will explain how to do it ;-)

Community
  • 1
  • 1
gtournie
  • 4,143
  • 1
  • 21
  • 22
  • User is going to fill the field by hand. I have a file input widget from http://jasny.github.io/bootstrap/javascript/#fileinput. – Patryk Jan 26 '14 at 23:11