Click here to Skip to main content
15,879,326 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 124.9K   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 
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.