0

I am building an MVC based ASP.NET application. One of the functionalities should be to be able to upload files asynchronously using a progress bar.

I've had success with uploading files without the progress bar. The code below does that.

View Code:

<input class="file" type="file" name="file" id="file" />
<input type="submit" name="submit" value="Upload" />

Controller Code:

    public ActionResult Upload(){
        return View();
    }

    [HttpPost]
    public ActionResult Upload(Resource resource)
    {
        try
        {
            if (resource.File.ContentLength > 0)
            {
                var fileName = Path.GetFileName(resource.File.FileName);
                var path = Path.Combine(Server.MapPath("~/Content/Resources"), fileName);
                resource.File.SaveAs(path);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Cannot upload file. Exception of type : {0}", e.ToString());
        }
        return RedirectToAction("Upload");
    }

This code works absolutely fine. With slight modifications, I am even able to upload multiple files. But, even though I've tried finding it, I am not able to upload files using a progress bar.

Any help is appreciated.

2 Answers 2

3

This is how I do it - the controller code is much the same, but the client has some javascript in it to monitor and update progress of the ajax posting. The UI Html is like this:

    <div id="uploadDetails" class="form-group">
        <div class="input-group">
            <span class="input-group-btn">
                <span class="btn btn-primary btn-file">
                    Browse&hellip; <input type="file" name="file" id="file" />
                </span>
            </span>
            <input type="text" id="filename" class="form-control fullwidth" readonly />
            <span class="input-group-btn">
                <button class="btn btn-primary" type="button" id="uploadFile"><span class="glyphicon glyphicon-upload"></span> Upload File </button>
            </span>
        </div>
    </div>

And the javascript for the upload like this:

    $(document).on('click', '#uploadFile', function (e) {
        var fileElement = document.getElementById('file');
        var file = fileElement.files[0];

        var formData = new FormData();
        formData.append("filename", fileElement.files[0].name);
        formData.append("id", '@Model.SharedIP.Id');
        formData.append("file", file, fileElement.files[0].name);

        var html = $('#uploadFile').html();
        $('#uploadFile').html('Uploading...');

        $.ajax({
            url: "@Url.Action("UploadFile", "SharedIP")",
            type: "POST",
            data: formData,
            processData: false,  // tell jQuery not to process the data
            contentType: false,   // tell jQuery not to set contentType
            xhr: function(){
                var xhr = new window.XMLHttpRequest();
                xhr.upload.addEventListener("progress", function(evt){
                    if (evt.lengthComputable) {
                        $('#uploadFile').html('Uploading... ' + Math.round((evt.loaded / evt.total) * 100) + '%');
                    }
                    else $('#uploadFile').html('hmmm');
                }, false);
                return xhr;             
            },
            success: function (results) {
                updateFilesList();
                $('#uploadFile').html(html);
                fileElement.files = [];
                var control = $('#file');
                control.replaceWith(control.clone(false));
                $('#filename').val("")
            },
            error: function (xhr, ajaxOptions, thrownError) {  
                $('#uploadFile').html(html);
                alert(xhr.responseText);  
            }  

        });
    });

For completeness, here's the Controller signature, it's .net Core RC1 so might not work in your target framework, but you will get the idea.

    [HttpPost]
    public IActionResult UploadFile(string filename, Guid id, IFormFile file)
    {
        IPFile ipfile = new IPFile()
        {
            ContentType = file.ContentType,
            DateUploaded = DateTime.Now,
            Filename = filename,
            SharedIPId = (id == Guid.Empty ? (Guid?)null : id), 
            Id = Guid.NewGuid(),
            UploadedBy = User.Alias(),
        };

        ipfile = FileManager.AddFileFromStream(User.Alias(), ipfile, file.OpenReadStream());

        return Ok(ipfile);
    }

Hope that answers your question.

[EDIT] Just realised this isn't a "progress bar" - but it's got all the workings and % display - to put a progress bar in, you'd just apply CSS to an element that renders the % graphically for you - see posts like http://www.w3schools.com/bootstrap/bootstrap_progressbars.asp for examples.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks a lot Russell. I'll mark it as an answer if I am able to successfully implement the progress bar from this also.
Thanks for the help Russell. But can you please share the code with the progress dialog. Help on this is much appreciated.
Hi Aditya - what code do you mean? The code above covers all of it?
I meant the code with the progress bar. I have tried different things, but I cannot do multiple file upload asynchronously using progress bar. Help is appreciated.
Send me what bit you're struggling with and why and I will see if I can help?
|
1

Here is the code that I have tried. It's a bare minimum code but works as expected. It still has some bugs and I would appreciate if someone could make it bug free.

Some bugs:

  1. Progress bar does not reset on a new file upload.
  2. Add a button to do the upload (I can do it myself as well).

Model Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace NewDeploymentsTesting.Models
{
    public class UploadFilesResult
    {
        public string Name { get; set; }
        public int Length { get; set; }
        public string Type { get; set; }
    }
}

Controller Code:

using NewDeploymentsTesting.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace NewDeploymentsTesting.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ContentResult UploadFiles()
        {
            var r = new List<UploadFilesResult>();
            foreach (string file in Request.Files)
            {
                HttpPostedFileBase hpf = Request.Files[file] as HttpPostedFileBase;
                if (hpf.ContentLength == 0) continue;
                string savedFileName = Path.Combine(Server.MapPath("~/Content/Resource"), Path.GetFileName(hpf.FileName));
                hpf.SaveAs(savedFileName);
                r.Add(new UploadFilesResult()
                {
                    Name = hpf.FileName,
                    Length = hpf.ContentLength,
                    Type = hpf.ContentType
                });
            }
            return Content("{\"name\":\"" + r[0].Name + "\",\"type\":\"" + r[0].Type + "\",\"size\":\"" + string.Format("{0} bytes", r[0].Length) + "\"}", "application/json");
        }
    }
}

View Code:

@{Layout = null;}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Uploading Files</title>
    <link href="~/Content/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="~/Content/bootstrap/bootstrap-theme.css" rel="stylesheet" />
    <link href="~/Content/jquery.fileupload.css" rel="stylesheet" />
    <script src="~/Scripts/jquery-1.9.1.min.js"></script>
    <script src="~/Scripts/jquery.ui.widget.js"></script>
    <script src="~/Scripts/bootstrap.min.js"></script>
    <script src="~/Scripts/jquery.fileupload.js"></script>

    <script type="text/javascript">
        $(document).ready(function () {
            $('#fileupload').fileupload({
                dataType: 'json',
                url: '/Home/UploadFiles',
                autoUpload: true,
                done: function (e, data) {
                    $('.file_name').html(data.result.name);
                    $('.file_type').html(data.result.type);
                    $('.file_size').html(data.result.size);
                }
            }).on('fileuploadprogressall', function (e, data) {
                var progress = parseInt(data.loaded / data.total * 100, 10);
                $('.progress .progress-bar').css('width', progress + '%');
            });
        });
    </script>
</head>
<body>
    <div class="container">
        <span class="btn btn-success fileinput-button">
            <i class="glyphicon glyphicon-plus"></i>
            <span>Add Files ...</span>
            <input id="fileupload" type="file" name="files[]" multiple />
        </span><br />
        <div class="progress">
            <div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
                <span class="sr-only">0% Complete</span>
            </div>
        </div><br />
        <div class="file_name"></div><br />
        <div class="file_type"></div><br />
        <div class="file_size"></div><br />
    </div>
</body>
</html>

Here is what it looks like on the browser window.

Before uploading a file.

After uploading the file

1 Comment

@Russell. I have updated the code. Can you help on this now?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.