I have a view which allow the user to upload multiple at a time as below
<label class="control-label">Files:</label>
<div id="fileUploadContainer">
<div id="uploadContainer" style="height:30px">
<input type="file" id="file1" name="file1" onchange="ValidateSingleInput(this);" />
</div>
<div class="controls">
<div id="fileappend">
<div id="fileappendContainer">
<output id="filesSize"></output>
</div>
</div>
</div>
</div>
<a id="btnAdd" href="#">Add Another</a>
Code "Add Another" Click:
$(function () {
$('#btnAdd').click(function (e) {
e.preventDefault();
var htmlFormatDiv = $("<div id='uploadContainer' style='height:30px'></div>");
var htmlFormatFile = $("<input type='file' onchange='ValidateSingleInput(this);' />");
var totalFileCount = $("#fileUploadContainer").children("div").length;
var fuData = document.getElementById('<%= file1.ClientID %>');
htmlFormatFile.attr("id", "file1");
htmlFormatFile.attr("name", "file1");
htmlFormatDiv.attr("id", "uploadContainer");
htmlFormatDiv.append(htmlFormatFile);
$("#fileUploadContainer").append(htmlFormatDiv);
$("#filesSize").append(htmlFormatDiv);
});
});
Code to restrict the file upload extension type and showing the file size
var _validFileExtensions = [".jpg", ".jpeg", ".pdf"];
function ValidateSingleInput(oInput) {
if (oInput.type == "file") {
var sFileName = oInput.value;
if (sFileName.length > 0) {
var fsize = sFileName.size;
if (fsize > 4048576) {
alert(fsize + " bites\nToo big!");
}
var blnValid = false;
for (var j = 0; j < _validFileExtensions.length; j++) {
var sCurExtension = _validFileExtensions[j];
if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).toLowerCase() == sCurExtension.toLowerCase())
{
blnValid = true;
$('#filesSize').append('Size - ' + ((oInput.files[0].size) / 1024 / 1024).toFixed(2) + 'mb' + '<br />');
break;
}
}
if (!blnValid) {
alert("Sorry, " + sFileName + " is invalid, allowed extensions are: " + _validFileExtensions.join(", "));
oInput.value = "";
return false;
}
}
}
return true;
}
Now when i Upload the files I am getting below O/P
The problem occurs when i click any of the existing browse button again browse another document. The size of the old file will remain there and the size of the new file will attach to the last filename irrespective of the browse button clicked.
Is there any way to avoid the same?
Also is there any other method which is simpler than this.
Controller
public ActionResult file_upload(IEnumerable<HttpPostedFileBase> file1)
{
foreach (var file in file1)
{
if (file != null)
{
if (file.ContentLength > 0)
{
}
}
}
}
You main issue is that your generating invalid html because of duplicate id
attributes and jQuery selectors such as $('#filesSize').append(...
will only select the first element with that id
. You need to use class names instead and use relative selectors to select the correct element to update.
I would however recommend a number of other changes to your implementation.
First, consider using a ValidationAttribute
for the file size which will give you both client and server side validation. Refer Client-side File Upload Size Validation in ASP.NET MVC for an example of implementing it.
Second, create a template that you can clone, update and append to the DOM. You current code is doing some strange things including adding the new div to both the <div id="fileUploadContainer">
and the first <output id="filesSize"> elements. Its not really clear why you are using an
element or what
var fuDatais (it would be
undefined`) or how its being used. Your view would be
@using (Html.BeginForm(.....))
{
<div id="fileUploadContainer"></div>
<a id="btnAdd" href="#">Add a file</a>
}
// template
<div id="template" style="display:none;">
<div class="uploadContainer" style="height:30px">
<input type="file" class="file" name="files" />
</div>
<div class="controls">
<div class="fileappend">
<div class="fileappendContainer">
<span class="filesSize"></span>
</div>
</div>
</div>
</div>
Then the scripts would be (excluding your validation code)
var container = $('#fileUploadContainer');
var template = $('#template');
$('#btnAdd').click(function() {
var clone = template.clone();
container.append(clone.html());
$(this).text('Add another file');
});
container.on('change', '.file', function() {
var file = $(this).get(0).files[0];
var fileSize = 'Size: ' + Math.round(file.size / 1024) + ' KB'
$(this).parent('.uploadContainer').next('.controls').find('.filesSize').text(fileSize);
});
Note, if you were to implement the FileSizeAtribute
, then there would be a few extra changes to the template (giving the input an indexed name attribute, including the data-val-*
attributes in the input and adding the html for the validation message) and you would need to reparse the validator when a new file input is added.