3

Using the helpful information I found here:

How can I upload files asynchronously?

I was able to get form data to the server-side with the following jQuery (very slightly modified from the link above):

$('#addFileInput').change(function () {
    var file = this.files[0];
    name = file.name;
    size = file.size;
    type = file.type;
    //Your validation
});

$('.submitFile').click(function () {
    var formData = new FormData($("#fileUploadForm"));
    $.ajax({
        url: '/AJAX Pages/Compute_File_Upload.cshtml',  //Server script to process data
        type: 'POST',
        xhr: function () {  // Custom XMLHttpRequest
            var myXhr = $.ajaxSettings.xhr();
            if (myXhr.upload) { // Check if upload property exists
                myXhr.upload.addEventListener('progress', progressHandlingFunction, false); // For handling the progress of the upload
            }
            return myXhr;
        },
        //Ajax events
        beforeSend: function () {
            $("#progressBar").css("visibility", "visible");
        },
        success: function (response) {
            $(".editLabelTitle").text(response);
        },
        //error: errorHandler,
        // Form data
        data: formData,
        //Options to tell jQuery not to process data or worry about content-type.
        cache: false,
        contentType: false,
        processData: false
    });
});

function progressHandlingFunction(e) {
    if (e.lengthComputable) {
        $('progress').attr({ value: e.loaded, max: e.total });
    }
}

Here's the HTML that is involved:

<div class=\"addFileBox\">
    <div class=\"editPageSubTitle dragHandle\">
        Add File
        <button id=\"closeAddFileBox\">X</button>
    </div>
    <div class=\"innerAddFileDiv\">
        <form id=\"fileUploadForm\" enctype=\"multipart/form-data\">
            <input id=\"addFileInput\" name=\"addFileInput\" type=\"file\" />
        </form>
        <br/>
        <progress id=\"progressBar\"></progress>
        <br/>
        <button class=\"submitFile\">Submit File</button>
    </div>
</div>

The Ajax request in and of itself works fine. The problem comes when I don't know how to get the file on the server-side code (normally I would just find the input with the Request.Files["someFileId"]) but as all formData is sent, this isn't working the way I am familiar with.

C# CODEBEHIND

@{
Layout = "";

if(IsAjax)
{
    var file = Request.Files["addFileInput"];

    var fileName = Path.GetFileName(file.FileName);
    var path = Path.Combine(Server.MapPath("~/CMS Files/UtilityBilling"), fileName);
    file.SaveAs(path);
}

}

What is the proper way to access the given file, considering my scenario and environment?

Community
  • 1
  • 1
VoidKing
  • 6,282
  • 9
  • 49
  • 81
  • 1
    Theoretically you'd access it the same way you would access it as if it were posted using a
    tag.
    – Kevin B Oct 09 '13 at 19:05
  • @KevinB That's the way my code is setup now, but I get an "Object reference not set to an instance of an object" error on the `var fileName = Path.GetFileName(file.FileName);` line. – VoidKing Oct 09 '13 at 19:31
  • @KevinB I've used `Request.Files` before on regular form posts. Are you sure it's supposed to be accessible the same way? I wonder... – VoidKing Oct 09 '13 at 20:00
  • I'm not familiar with asp/C#, all i know is sending an ajax request using a FormData object as data with the POST datatype should mimic that of a normal form post. Did you include the proper enctype, just like you would need to on a normal form element that's posting files? – Kevin B Oct 09 '13 at 20:03
  • @KevinB If you mean putting the `enctype` attribute in the form tag like: `
    ` Then yes, I did exactly that.
    – VoidKing Oct 09 '13 at 20:31
  • well, did you add that to the $.ajax options too? $.ajax doesn't exactly look at your form for it's options. – Kevin B Oct 09 '13 at 20:32
  • Nevermind, that isnt' a requirement. Here's another similar question with a highly upvoted answer, does it help? http://stackoverflow.com/questions/166221/how-can-i-upload-files-asynchronously-with-jquery – Kevin B Oct 09 '13 at 20:34
  • It does help, but in my post, that's the question I linked to that got me started on this. According to that answer, what I'm doing *should* work. Yet, it doesn't... – VoidKing Oct 09 '13 at 20:42

1 Answers1

2

Try this from codebehind:

        HttpFileCollection filesCollection = HttpContext.Current.Request.Files;
        var fileName = filesCollection[0];
        string filePath = Path.Combine(HttpContext.Current.Server.MapPath("~/SaveDir"), fileName.FileName);
        fileName.SaveAs(filePath);
christiangobo
  • 520
  • 1
  • 7
  • 19
  • Well, I shouldn't really do it that way because I am not dealing with a collection of files, just a single one at a time. – VoidKing Oct 09 '13 at 19:39
  • I'll try it anyway, though, I will have to use this in a for or foreach loop, though, no? – VoidKing Oct 09 '13 at 19:42
  • Okay I tried `foreach (var file in filesCollection) { var fileName = Path.GetFileName(file.FileName); var path = Path.Combine(Server.MapPath("~/CMS Files/UtilityBilling"), fileName); file.SaveAs(path); }` – VoidKing Oct 09 '13 at 19:46
  • @VoidKing that is a Collection, you can access the files using his index ex: filesCollection[0].FileName – christiangobo Oct 09 '13 at 19:46
  • But got this error: `'object' does not contain a definition for 'FileName' and no extension method 'FileName' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)` On the same line that I said errored before. – VoidKing Oct 09 '13 at 19:46
  • I know what it is, I'm just saying I shouldn't have to use a collection for what I know will ALWAYS be a single file. Plus it errors anyway (though it is starting to seem like it is because of the code I got from the site I linked at the top of my question). – VoidKing Oct 09 '13 at 19:47
  • @VoidKing HttpFileCollection filesCollection = HttpContext.Current.Request.Files; string fileName = filesCollection[0].FileName; – christiangobo Oct 09 '13 at 19:55
  • Are you saying that I can't get this data in a way that let's me use `Path` method? – VoidKing Oct 09 '13 at 19:58
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/38915/discussion-between-christian-and-voidking) – christiangobo Oct 09 '13 at 20:11
  • 1
    Well, here is what I've gathered. Using the methods shown in my post it *should* mimic a regular form post. However, I was not able to access individual files by name (I have successfully used `Request.Files["inputName"]` on a regular form post before and, again, it *should* work... but it doesn't. That having been said, this answer at least gets it working, even if it is a little differently than I wanted. Thanks Christian. – VoidKing Oct 09 '13 at 20:54
  • @christiangobo - How can I call a server-side function? I created a new XMLHTTPREQUEST obj : xhr.open("POST", "Login.aspx/test", true); and call xhr.send(formData), but I never get to the server side function – Inbal Dec 22 '13 at 11:08
  • @Inbal I realize your comment is a little over 4 years old now, but might want to ask the question in SO as a new question, while referencing this one. But if you (or someone like you that finds this) can't get the server-side to respond, use tools in the browser (hit F12 in Chrome, then click Console) to find out what the error might be. That would get you started. – vapcguy Mar 09 '18 at 02:10