-1

I am using cshtml as view

this is my input:

@Html.TextArea("DESCRIPTION", null, new { @class = "field-longtext", @cols = 100, @rows = 5, maxlength = 255 })

@Html.TextBox("DOC_TYPE", null, new { @class = "field-longtext", maxlength = 10 })

@Html.TextBox("DOC_FILE", null, new { @class = "field-longtext", @type = "file" })

and using ajax post

function UploadFile() {

    var url = '@Url.Action("CreateUploadFile")';
    var data = {};
    var result = false;

    $('#@ViewBag.FormName').find('input, textarea').each(function () {
        data[$(this).attr('name')] = $(this).val();
    });

    data.PROBLEM_CALL_ID = @Model.Model.PROBLEM_CALL_ID;

    $.ajax({
        type: 'POST',
        url: url,
        data: data,
        async: false,
        success: function (data) {
            if (data.result) {
                var selectedRow = SubFormService.tableList['#@ViewBag.TableName'].selectedRow;
                result = true;
            } else {
                alert(data.errorMsg);
                result = false;
            }
        }
    });

    return result;
}

My Controller:

    [HttpPost]
    public ActionResult CreateUploadFile(Models.Shared.DocumentModel vm)
    {
        var id = -1;
        var result = string.Empty;
        var json = new BasicJsonResult();

        var file = vm.DOC_FILE;

        LogUtility.Debug(file.ContentLength.ToString());
        if (file != null && file.ContentLength > 0)
        {
            var fileName = Path.GetFileName(file.FileName);
            LogUtility.Debug(fileName);
            LogUtility.Debug(Server.MapPath("~/Images/"));
            var path = Path.Combine(Server.MapPath("~/Images/"), fileName);
            file.SaveAs(path);
        }

        return Json(json, JsonRequestBehavior.AllowGet);
    }

the code var file = vm.DOC_FILE; warns me (Object reference not set to an instance of an object.), but I can get another control value (vm.DESCRIPTION, vm.DOC_TYPE).

Please help.

Also, I want to download file when that file is uploaded.

S.Serpooshan
  • 7,608
  • 4
  • 33
  • 61

2 Answers2

3

With the introduction of XHR2 it is now possible to upload files using AJAX. You could use FormData to achieve this. Assuming that your input elements are inside a <form> you may try this (also include in this form a hidden input for the PROBLEM_CALL_ID field so that it gets sent to the server):

function UploadFile() {
    var url = '@Url.Action("CreateUploadFile")';
    var formData = new FormData($('form')[0]);
    var result = false;

    $.ajax({
        type: 'POST',
        url: url,
        data: formData,
        async: false,
        success: function (data) {
            ...
        }
    });

    return result;
}

So just make sure that you have wrapped your input elements inside a form tag (preferably with an id so that you can more specifically select it):

<form id="myForm">
    @Html.TextArea("DESCRIPTION", null, new { @class = "field-longtext", @cols = 100, @rows = 5, maxlength = 255 })

    @Html.TextBox("DOC_TYPE", null, new { @class = "field-longtext", maxlength = 10 })

    @Html.TextBox("DOC_FILE", null, new { @class = "field-longtext", @type = "file" })

    @Html.HiddenFor(x => x.PROBLEM_CALL_ID)
</form>

and then select the form like this:

var formData = new FormData($('#myForm')[0]);

Also please, please, please don't do that:

async: false

By doing this you are defeating the whole purpose of an asynchronous call to the server. If you set this flag the browser will freeze during the file upload which is an absolutely horrible user experience. If you do this, then you'd better use a normal HTML form submit to upload the file - you are loosing all the benefits of AJAX and there's no point to be making an AJAX request with this flag set to true.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Hi... when I change to var data = new FormData($('#@ViewBag.FormName')[0]); It throws exception Uncaught TypeError: Illegal invocation. when I print out the information of data, just like below {"DOC_FILE": "C:\\fakepath\image1-11.png", "DESCRIPTION":"asdasd","DOC_TYPE":"123"} I don't know why it shows C:\\fakepath\.. the directory of file should C:\\Desktop\.... – Kimkwan Lau Jan 22 '17 at 11:25
  • The reason for this is because of security reasons only the filename is sent to the server. The directory on the client is obfuscated and it will never reach your server. This is by design and you cannot rely on retrieving the full directory structure on your server. – Darin Dimitrov Jan 22 '17 at 14:29
-1

If you want to able upload a file using ajax, you should use iframe.

<iframe name="upload-data" id="upload-data" frameborder="0" width="0" height="0"></iframe>
<form id="frm-add-update" enctype="multipart/form-data" method="post" target="upload-data"> 
    // HTML Code 
</form>

In my case, my Controller would return a code, "0x001" if the upload process successful, otherwise it will return "0x00".

When document is ready

    $("#upload-data").hide();
    $("#upload-data").load(function () {
        var data = $.parseJSON($("#upload-data").contents().text());
        if (data != null) {
            if (data.code != "0x001") {
                // you got a problem
            }
            else {
                // you got no problem
            }
        }
    });

In Controller

[Authorize, HttpPost]
    private JsonResult ActionNAme(ModelClass modelObj, HttpPostedFileBase htmlFileTagName)
    {
        string code = "0x001";
        string message = "";
        try
        {
            // your process here
        }
        catch(Exception)
        {
            code = "0x000";
            message = ex.Message;
        }

        return new JsonResult()
        {
            Data = new
            {
                code = code,
                message = message
            }
        };
    }

For downloading the uploaded file, i think you should change the Action return type. You will get the information from this link.

Hope it can solve your problem :)

Community
  • 1
  • 1
  • Posting to an iframe is only necessary if the user's browser doesn't support the [File API](https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications). – Tieson T. Jan 22 '17 at 07:03