Click here to Skip to main content
15,888,351 members
Articles / Web Development / HTML
Tip/Trick

Multiple File Upload in MVC

Rate me:
Please Sign up or sign in to vote.
4.97/5 (13 votes)
7 Aug 2014CPOL2 min read 125.2K   6.3K   21   34
Multiple file upload in MVC

Introduction

I had a requirement in MVC 4 application - A multi file uploader control that has options:

  • Select multiple files at a time
  • Select from different folder
  • List all selected files
  • Remove files from the list (Filtering)
  • When submitting - Save only filtered one
  • Get page model also in the Action
  • Save attachments after saving the model saving or some business logic

Issues I Faced

I was getting the partial needs - Uploader control, but Model received is empty - at Action in our controller.
When Model is filled, the filtered list is incorrect (deleted files also appeared).

How I Solved It

I created a JS script that will make the <input type="file" /> control get recreated and preserve the HttpPostedFileBase files + removed/filtered files in a Hidden field - This maintains the filtration in deleting selected files also.

When user puts some files in the fileupload control, "onchange" event, it will hide the control and create a similar control and place there and allow users to select again. The selected files are taken and maintained in a Hidden field appending its names. With these names - we can filter the posted files list (List<httppostedfilebase>) in our action. So while passing Model - keep this hidden field value.

Using the Code

Please find the source code attached here for the full demo.

I will explain how it works. See the code snippet below.

Given below is the snippet of HTML that has a fileUploader and a button that submits to our server action.

HTML
@using (Html.BeginForm("UploadAction", "Home", 
FormMethod.Post, new { enctype = "multipart/form-data", id = "frmID" }))
{
    @Html.HiddenFor(i => i.FilesToBeUploaded)

    <div class="labelstyle">
        <label>Files</label>
    </div>

    <div id="uploaders">
        <input type="file" id="fileToUpload" 
        name="fileUpload" multiple="multiple" style="float: left;" />
        <br />
        <span id="spnFile" style="float: left; color: #FF0000"></span>
        @Html.ValidationMessage("File")
        @Html.Hidden("hdnFileUpload")
    </div>
    <br />
 <div class="col-lg-6">
        <button class="btn btn-primary" id="btnAddIssue" type="submit">Submit</button>
    </div>
    <br />
    <div class="control-section" style="padding: 0px;">
        <div id="selectedFiles"></div>
    </div>
}

This portion is the script that is responsible for creation of the multi file upload and hiding the previous uploader + storing the filtered attachments to a hidden field.

HTML
<script src="~/Scripts/jquery-1.7.1.js"></script>

<script>
    var nowTemp = new Date();
    var now = new Date(nowTemp.getFullYear(), nowTemp.getMonth(), nowTemp.getDate(), 0, 0, 0, 0);
    var files;
    var storedFiles = [];
    var upc = 0;   

    $(function () {

        $(":file").attr('title', '  ');
        var $loading = $('#loadingDiv').hide();

        $("input[id^='fileToUpload']").change(function (e) {
            doReCreate(e);
        });

        selDiv = $("#selectedFiles");
    });

    function doReCreate(e) {
        alert('a');
        upc = upc + 1;
        handleFileSelect(e);

        $("input[id^='fileToUpload']").hide();

        $('<input>').attr({
            type: 'file',
            multiple: 'multiple',
            id: 'fileToUpload' + upc,
            class: 'fUpload',
            name: 'fileUpload',
            style: 'float: left',
            title: '  ',
            onchange: "doReCreate(event)"

        }).appendTo('#uploaders');
    }

    function handleFileSelect(e) {

        //selDiv.innerHTML = ""; storedFiles = []; 
        selDiv = document.querySelector("#selectedFiles");

        if (!e.target.files) return;

        //selDiv.innerHTML = "";
        files = e.target.files;

        for (var i = 0; i < files.length; i++) {
            //if (i == 0) { selDiv.innerHTML = ""; storedFiles = []; }
            var f = files[i];
            selDiv.innerHTML += "<div>" + f.name + 
            "<a onclick='removeAtt(this)'> X </a></div>";
            storedFiles.push(f.name);
        }
        $('#@Html.IdFor(i => i.FilesToBeUploaded)').val(storedFiles);
    }

    function removeAtt(t) {
        var serEle = $(t).parent().text().slice(0, -3);
        var index = storedFiles.indexOf(serEle);
        if (index !== -1) {
            storedFiles.splice(index, 1);
        }
        $(t).parent().remove();

        $('#@Html.IdFor(i => i.FilesToBeUploaded)').val(storedFiles);

    }
</script>

And find the server code, where it receives the model + hidden element and the full attachments that we need.

C#
[HttpPost]
       public ActionResult UploadAction(AnyModel model, List<HttpPostedFileBase> fileUpload)
       {
           // Your Code - / Save Model Details to DB

           // Handling Attachments -
           foreach (HttpPostedFileBase item in fileUpload)
           {
               if (Array.Exists(model.FilesToBeUploaded.Split(','), s => s.Equals(item.FileName)))
               {
                   //Save or do your action -  Each Attachment ( HttpPostedFileBase item )
               }
           }
           return View("Index");
       }

Also, if style "X" to remove selected files, update your script code accordingly.

Points of Interest

This is a simple one and a tricky approach - Recommended for small file(s) size - But can be any number of files .

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
India India
Am a software Developer
Working in mostly MS Platform, interested in scripting languages.

Am from South India - Kerala Smile | :)

Rigin

Comments and Discussions

 
QuestionRemoving file still send HttpPostedFileBase to server Pin
MT_13-Nov-18 21:34
professionalMT_13-Nov-18 21:34 
QuestionBingo Pin
Member 134991202-Nov-17 19:44
Member 134991202-Nov-17 19:44 
Questionhi Pin
Ejaz Qadir4-Oct-17 5:17
Ejaz Qadir4-Oct-17 5:17 
QuestionFixed additional data being sent to server Pin
karlpdotcom18-Nov-15 21:42
karlpdotcom18-Nov-15 21:42 
AnswerRe: Fixed additional data being sent to server Pin
Rigin VP3-Dec-15 4:25
Rigin VP3-Dec-15 4:25 
AnswerRe: Fixed additional data being sent to server Pin
Member 1050600315-Jun-17 2:00
Member 1050600315-Jun-17 2:00 
Questionprepopulate files to upload Pin
Member 1193506328-Sep-15 9:44
Member 1193506328-Sep-15 9:44 
AnswerRe: prepopulate files to upload Pin
Rigin VP28-Sep-15 20:10
Rigin VP28-Sep-15 20:10 
QuestionNot cross-browser compatible - check here for su Pin
Cody Christian28-Apr-15 13:03
Cody Christian28-Apr-15 13:03 
files.length and e.target will require tweaks to work in all browsers. you can redefine e if it doesn't exist by saying,
JavaScript
if (!e) e = window.event;
Then replace the e.target.property with
JavaScript
(e.srcElement || e.target).property
This should work for older browsers (IE9+). I can't remember files.length off the top of my head like the others, but I think it's
JavaScript
(e || e.files).length
Basically the || is like saying OR, so it's going to check the first object and if it isn't null or error out, it'll check the second object. This explanation may not be 100% accurate, but that's how I remember it logically. Then by appending the .property at the end, you're calling the property of one or the other, whichever one will work for whichever browser the client is using.
Questioncant save files to folder Pin
Member 1154163220-Mar-15 7:17
Member 1154163220-Mar-15 7:17 
Questionsame code are not working with IE 9.0 Pin
krish.singh17-Feb-15 9:28
krish.singh17-Feb-15 9:28 
AnswerRe: same code are not working with IE 9.0 Pin
Rigin VP17-Feb-15 9:38
Rigin VP17-Feb-15 9:38 
GeneralRe: same code are not working with IE 9.0 Pin
krish.singh18-Feb-15 5:03
krish.singh18-Feb-15 5:03 
Questionsame code isnt working in IE Pin
Naveen861117-Feb-15 8:11
Naveen861117-Feb-15 8:11 
AnswerRe: same code isnt working in IE Pin
Rigin VP17-Feb-15 8:35
Rigin VP17-Feb-15 8:35 
Generalhow to store image Pin
Prasenjit Dutta6-Jan-15 0:05
Prasenjit Dutta6-Jan-15 0:05 
AnswerRe: how to store image Pin
Rigin VP6-Jan-15 2:29
Rigin VP6-Jan-15 2:29 
GeneralRe: how to store image Pin
Rigin VP11-Jan-15 19:19
Rigin VP11-Jan-15 19:19 
QuestionSource Code is missing Pin
snprani27-Oct-14 19:55
snprani27-Oct-14 19:55 
QuestionMissing Zip Pin
Member 1116390218-Oct-14 18:01
Member 1116390218-Oct-14 18:01 
AnswerRe: Missing Zip Pin
Member 1116390218-Oct-14 18:03
Member 1116390218-Oct-14 18:03 
Answerfile upload Pin
Chhabra_Ankur30-Sep-14 21:38
Chhabra_Ankur30-Sep-14 21:38 
GeneralRe: file upload Pin
Rigin VP1-Oct-14 1:28
Rigin VP1-Oct-14 1:28 
GeneralRe: file upload Pin
Chhabra_Ankur6-Oct-14 20:05
Chhabra_Ankur6-Oct-14 20:05 
GeneralRe: file upload Pin
Rigin VP6-Oct-14 22:26
Rigin VP6-Oct-14 22:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.