1

Hi Im having some issues getting a file attaced to a form to submit on jquery .post().

What i want to do is, user choose a file / the form submit using jquery .post(). I got it working fine if i just do a .submit() on the whole form, but i dont want to use it because of other content on the site. here is the code i use now. what this does is use a button as file input and i do the submit on the choose function right away.

$('.upload').file().choose(function (e, input) {                
            input.attr('name', 'firstPicture');
            input.hide();

            $(input).appendTo('#myForm');

            $('#hiddenDiv').show();

            $.post("/Home/UploadSingelFile", $("#myForm").serialize());
            return false;
        });

my action is correct public ActionResult UploadSingelFile(HttpPostedFileBase firstPicture)

what happends when i do like above is that the firstPicture input is null, but like i said if i do the submit its ok.

if this is not possible do im thinking of doing a .submit() but then i need to return a partialview and how would i go about to update that partialview into a div on the return? just like microsofts ajax.form got a updatetarget (i dont want to use their ajax form)

Can Gencer
  • 8,822
  • 5
  • 33
  • 52
Dejan.S
  • 18,571
  • 22
  • 69
  • 112

2 Answers2

1

When sending an AJAX request using jQuery you are simply sending a application/x-www-form-urlencoded request to the server whereas in order to upload a file you need to use a multipart/form-data request.

There are some plugins such as jquery form which emulate this functionality by using a hidden iframe. So basically you will write the following to ajaxify the form containing file inputs:

$(function() {
    $('#myForm').ajaxForm(function(result) {
        // do something with the results when the form is submitted
    });
});

and then when you need to submit the form:

$('#myForm').ajaxSubmit();

or simply when the user presses the submit button.

There are also other plugins such as Uploadify and Plupload which would allow yoiu to achieve the same (Uploadify for example uses Flash, while Plupload detects what the client supports: Flash, Silverlight and if not it may fallback to hidden iframes to simulate the file upload).

But you may simply forget about uploading files with $.post.


UPDATE:

As @Can Gencer points out in the comments section there's also the Ajax upload plugin which could be used.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Uploadify is my favourite, but to be fair I have never tried plupload, I will before too long though. – Liam Bailey Jul 24 '11 at 12:12
  • @Liam Bailey, I like Plupload for its capacity to detect what the client supports and fallback to it and not rely exclusively on Flash. – Darin Dimitrov Jul 24 '11 at 12:17
  • actually some browsers support uploading files through AJAX, if i'm not mistaken. – Can Gencer Jul 24 '11 at 12:25
  • @Can Gencer, there is a working draft for the [File API](http://www.w3.org/TR/FileAPI/) in HTML5 that some browsers support. – Darin Dimitrov Jul 24 '11 at 12:29
  • Yep, but not all I believe. I've used Ajax Upload (http://valums.com/ajax-upload/) to some success before. Maybe you should rephrase to say that you can't use jquery to upload files using ajax. – Can Gencer Jul 24 '11 at 12:33
  • @Can Gencer, good point. Indeed this plugin writes the file contents directly to the request body. – Darin Dimitrov Jul 24 '11 at 12:40
  • @Dejan.S, of course that you can use it. Notice however that this plugin writes the file directly to the request stream so inside the controller action that is supposed to handle the file upload you will have to read it from `Request.InputStream` directly. – Darin Dimitrov Jul 24 '11 at 14:29
  • so i use binaryreader, memorystream and Image to save this Request.inputstream? u got any suggestions on this? – Dejan.S Jul 24 '11 at 14:54
  • @Dejan.S, yes you could use a `byte[]` which will be initialized to the length of the request stream: `byte[] image = new byte[Request.InputStream.Length];` and then you will read from it `Request.InputStream.Read(image, 0, image.Length);` and finally you will do something with the image. – Darin Dimitrov Jul 24 '11 at 14:56
  • hm sorry but Darin how do i save it? – Dejan.S Jul 24 '11 at 15:03
  • @Dejan, I think the input parameter name must be "qqfile" on your action method for it to get a HttpPostedFile. Can you give that a try? You shouldn't need to parse the stream manually. – Can Gencer Jul 24 '11 at 15:04
  • 1
    @Dejan. S, you may take a look at the following thread: http://stackoverflow.com/questions/4884920/mvc3-valums-ajax-file-upload/4895699#4895699 – Darin Dimitrov Jul 24 '11 at 15:06
  • nice find Darin, my app was written in python and there was some different handling there as well, for IE and Firefox. Will update my answer. – Can Gencer Jul 24 '11 at 15:19
1

To complement Darin's answer, I've done this before using the Ajax upload script before and it worked quite well, and I think it's the most lightweight solution of the ones we tried at the time. It works across all browsers and does not need any flash or silverlight.

All you need to do is create a div as such:

<div id="file-uploader"></div>

and initialize the uploader like this:

var uploader = new qq.FileUploader({
    // pass the dom node (ex. $(selector)[0] for jQuery users)
    element: document.getElementById('file-uploader'),
    // path to server-side upload script
    action: '/Home/UploadSingelFile'
});

This should give you the HttpPostedFile parameter that you need in your action method. To update the view afterwards you can use different callbacks such as :

onSubmit: function(id, fileName){},
onProgress: function(id, fileName, loaded, total){},
onComplete: function(id, fileName, responseJSON){},
onCancel: function(id, fileName){},

Update:

To get the uploaded file on the ASP.NET MVC side, you need to do some more work. See the answer to this question: MVC3 Valums Ajax File Upload. (credit to Darin)

Community
  • 1
  • 1
Can Gencer
  • 8,822
  • 5
  • 33
  • 52
  • could you give me a simple example on how you use the oncomplete? or any of the onX – Dejan.S Jul 24 '11 at 14:58
  • @Dejan.S sure: onComplete: function(id, fileName, responseJSON) { if (responseJSON["success"] === true) alert("File uploaded successfully!"); } In your upload action you need to have return Json(new { success = true }); as the return. – Can Gencer Jul 24 '11 at 14:59
  • one thing tho why do i always get failed on upload even tho the file is uploaded? like the text that shows the progress and mb – Dejan.S Jul 24 '11 at 15:33
  • 1
    do you do return Json(new { success = true }); ? – Can Gencer Jul 24 '11 at 15:39