0

Trying to save a file to a db. I am using formData via javascript to append the file and adding this as a post object via ajax. for some reason nothing gets sent.

What am I doing wrong?

HTML

<input type="file" style="display: none;" class="btn btn-primary uploadFile">

script:

        $(".saveImage")
            .on("click",
                function() {
                  var files = $(".uploadFile");
                  var data = new FormData();


                  data = $.OverWatch.worker.uploadFileHandler.addUploadFiles(files, data);


                    $.OverWatch.worker.postUserData("/Administration/AddUserImage", data, function () {
                        alert("done");
                    });

                });

Functions above look like:

        addUploadFiles: function (files, data) {
            $.each(files, function (i, v) {
                var file = $(this).data("files");
                data.append("file", file);
            });

            return data;
        }

postUserData:

    postUserData: function(url, data, callback) {

        $.LoadingOverlay("show");
        $.ajax({
            url: url,
            type: 'POST',
            data: data,
            cache: false,
            processData: false,
            contentType: false,
            dataType: "HTML",
            success: function(data) {

                if (callback) {
                    callback(data);
                    $.LoadingOverlay("hide");
                }

            },
            error: function(event, jqxhr, settings, thrownError) {
                //$.helpers.errorHandler($("#fileDialogErrors"), event.responseText);
                var h;
                $.LoadingOverlay("hide");
            }
        });
    },

backend:

    public ActionResult AddUserImage()
    {
        if (Request.Files.Count != 0)
        {
           //save
        }

        return null;
    }

edit:

 var files = $(".uploadFile");

returns:

enter image description here

ThunD3eR
  • 3,216
  • 5
  • 50
  • 94
  • What is `var file = $(this).data("files");` returning? –  Apr 06 '17 at 00:22
  • @StephenMuecke check edits – ThunD3eR Apr 06 '17 at 00:29
  • You still have not answered my question :) - I'll bet it returns `undefined` –  Apr 06 '17 at 00:39
  • 1
    What you want is `var file = v.files[i];` to get the file(s) from each input. But you can simply use `var data = new FormData($('form').get(0));` which will correctly serialize all your inputs (refer [this answer](http://stackoverflow.com/questions/29293637/how-to-append-whole-set-of-model-to-formdata-and-obtain-it-in-mvc/29293681#29293681)). And you really should be using `public ActionResult AddUserImage(IEnumerable files)` to bind your file inputs. –  Apr 06 '17 at 00:49
  • @StephenMuecke you are compleatly right! My focus was on a diffirent part of the code so I never even checked there. Done this before in other projects with no problems but the bad habbit of compyg code from an old project and forgetting that I have done modifications:(. present this as an answer please. – ThunD3eR Apr 06 '17 at 00:52

3 Answers3

3

Your var file = $(this).data("files"); line of code would be returning undefined (unless you have some other javascript adding a data value, but you cannot add files to data so it in any case it would not be returning a file).

Change your loop to

$.each(files, function (i, v) {
    for (i = 0; i < v.files.length; i++) {
        var file = v.files[i];
        data.append("file", file);
    }
});

However, you can simplify this by using var data = new FormData($('form').get(0)); which will serialize all you form controls including file inputs to FormData (refer how to append whole set of model to formdata and obtain it in MVC for more information).

I also recommend you change your method signature to

public ActionResult AddUserImage(IEnumerable<HttpPostedFileBase> files)

and let the DefaultModelBinder do its magic.

Community
  • 1
  • 1
1

you can directly get file from controller when called using Request.Files

//(Request) HttpRequestBase object for the current HTTP request
if (Request.Files.Count > 0)//// Is image is uplaod by browse button
{
   var inputStream = Request.Files[0].InputStream;
   using (var binaryReader = new BinaryReader(inputStream))
   {
       var ImageBytes = binaryReader .ReadBytes(Request.Files[0].ContentLength); // same as you can get multiple file also
   }
   var fileExtension = Path.GetExtension(Request.Files[0].FileName);
}

thanks.

Lalji Dhameliya
  • 1,729
  • 1
  • 17
  • 26
  • OP is not asking how to get the files in the controller. The issue is the files are never sent in the request :) –  Apr 06 '17 at 07:21
0

I haven't done it with jQuery but just learned how to do it myself yesterday using plain old javascript... the following worked for me. If you want to stick with jquery maybe you can translate the functions to what you need:

var formElement = document.querySelector("form");
var payload = new FormData(formElement);

function onStateChange(ev) {
     // Check if the request is finished
     if (ev.target.readyState == 4) {
         editor.busy(false);
         if (ev.target.status == '200') {
             // Save was successful, notify the user with a flash

         } else {
             // Save failed, notify the user with a flash

         }
     }
};

xhr = new XMLHttpRequest();
xhr.addEventListener('readystatechange', onStateChange);
xhr.open('POST', '/posts');
xhr.send(payload);

Maybe see if using the above code works for you (it just targets a form that you have on the same page), and then you can troubleshoot whether it's your script that's the problem or a backend / communication problem.

Dustin S
  • 80
  • 7