Validate File size before upload - c#

I need to validate the file which is to be uploaded to the server. The validation must be done before uploading it. i.e., validation completed at client side. This task should be accomplished in ASP.NET MVC3 Webpage. It should also work with all browsers. IE9,8,7/FF/Chrome. I came to know that IE doesn't have FileReader API.
My Question is, How to Validate file size before Uploading in a MVC3 Webpage.

You can achieve by using jquery:
#
<span>
<b>Attachment</b> (8 MB only)<label id="attached" style="color:red; margin-left:5px"></label>
</span>
<input type="file" id="Attachment" name="Attachment" class="admin_textfeildmedium" value="" style="width:551px" accept="image/*">
#
jQuery(document).ready(function () {
jQuery('#Attachment').bind('change', function () {
//fileUpload = 0;
var iSize = (this.files[0].size / 1024);
if (iSize / 1024 > 1) {
if (((iSize / 1024) / 1024) > 1) {
fileUpload = 0;
} else {
iSize = (Math.round((iSize / 1024) * 100) / 100);
if (iSize <= 8) {
fileUpload = 1;
} else {
fileUpload = 0;
}
}
} else {
fileUpload = 1;
}
if (fileUpload == 0) {
// alert("Your attachment exceeded 8MB.");
jQuery('#attached').html('Your attachment exceeded 8MB.');
jQuery('#Attachment').val('');
}
});
});

.Net MVC Solution:
I am using the data type of HttpPostedFileBase
In your Views > Shared Folder, create a new folder called "EditorTemplates" and use this:
#model HttpPostedFileBase
#Html.TextBox("", null, new { type = "file" })
I then pass this HttpPostedFileBase object from the controller to a method that does the following:
public Files Upload(HttpPostedFileBase files)
{
if (files.ContentLength > 0) {
.....
}
The ContentLength property on the HttpPostedFileBase class contains the number of bytes in the posted file
This will make it so you have a file uploading box available.
On the ASP.NET WebForms Solution:
<asp:FileUpload ID="fuPictures" runat="server" />
Make a button with a OnClick or OnCommand event that does something like this:
if (fuPictures.HasFile == true)
{
int fileSize = fuPictures.FileBytes;
}
That will give you the file size. Hope this helps.

When it comes for a browser that supports HTML 5, it can be easily achieved with simple javascript:
Html Syntax
<input type="file" id="myFile" />
Javascript syntax
//gets the element by its id
var myFile = document.getElementById('myFile');
//binds to onchange event of the input field
myFile.addEventListener('change', function() {
//this.files[0].size gets the size of your file.
alert(this.files[0].size);
});
BUT, when it comes to an older browser (and we are all looking to you, Internet Explorer), the only way to do that on the client side is by using ActiveX:
var myFile = document.getElementById('myFile');
var myFSO = new ActiveXObject("Scripting.FileSystemObject");
var filepath = myfile.file.value;
var thefile = myFSO.getFile(filepath);
var size = thefile.size;
alert(size + " bytes");

Related

Passing multiple files as array or list from AJAX to Controller

I am trying to upload multiple files and then passing it to my Action in controller. The code is working fine but I am sure it can be made better because right now I am doing it sort of manually.
I am getting number of records from database against which I want to show file upload element. Number of records is not fixed, and it could be anywhere from 1 to 10 or may be more.
HTML Code
#{
foreach(FileModel fileModel in Model.FileModel)
{
<input type="file" id="#("originalFile" + i)" />
}
}
AJAX Code
for(i = 1; i <= #Model.FileModel.Count; i++)
{
if($("#originalFile" + i).val() == "")
{
alert("You must upload all files");
return false;
}
else
model.append("originalFile" + i, $("#originalFile" + i)[0].files[0]);
}
C# Code
[HttpPost]
public ActionResult UploadFiles(string masterRecordID, HttpPostedFileBase originalFile1 = null, HttpPostedFileBase originalFile2 = null, HttpPostedFileBase originalFile3 = null, HttpPostedFileBase originalFile4 = null, HttpPostedFileBase originalFile5 = null)
{
}
As you can see above is poor code as I am manually passing all files one by one. And number of files could be anything so how can make it dynamic i.e. somehow passing array or object of files from AJAX and then reading them all in controller?
Actually, #QingGuo's answer (which he previously deleted) is correct in the concept.
Your UploadFiles API action needs to modify for originalFiles parameter as array/list to support multiple files.
public ActionResult UploadFiles(string masterRecordID, HttpPostedFileBase[] originalFiles)
And in your JS part:
model.append("originalFiles", $("#originalFile" + i)[0].files[0]);

How to Retain HttpPostedFileBase on View Return

I have the following model:
public string Content { get; set; }
public HttpPostedFileBase LogoImageFile { get; set; }
View:
#Html.EditorFor(model => model.Content, new { htmlAttributes = new { #class = "form-control" } })
<div class="uploaded-img-wrapper hidden">
<img class="img-thumbnail-md" title="logo image" alt="logo image" />
</div>
#Html.TextBoxFor(model => model.LogoImageFile, new { type = "file", #class = "image-upload" })
When user select a photo from the local drive using the 'choose file' button from the file input element, the image will be displayed on the screen by javascript (Image will be saved to the server if form is valid and get submitted):
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
var $wrapper = $(input).prev();
$wrapper.removeClass('hidden');
$wrapper.find('img').attr('src', e.target.result).removeAttr('title');
$(input).addClass('hidden');
}
reader.readAsDataURL(input.files[0]);
}
I have a server side validation for the "Content" textbox. If it fails server side validation and the return View(Model); got called, the image from the file input will disappear. Anyone knows how to keep the file on the page when View is returned?
I have two solution for your problem:
Remote Validation:
according to following sentence "I have a server side validation for the Content textbox", in my view you can use remote validation for validate your form instead send your form to server.This link can help you to using Remote Validation(I would recommend this).
Temporary Store
In this solution you must use ajax-enabled file-upload component (such as this) to send file or files to server. Then you must prepare a action in order to receive file and save it in temporary storage such as (cache or file system) and generate a file-reference to restore the saved file and finally return the file-reference to client.The client insert received file-reference to form as a hidden input thus from then each time form sent, send file-reference instead file content.Of course two points should be noted:
1) Prepare a action to cancel a selected file with user request
2) Prepare a api for restore temporary file by file reference
3) Manage the temporary files to make sure that those don't fill your storage(if using asp.net cache as temporary storage the IIS itself handle it).
public ActionResult UploadTemporary(HttpPostedFileBase file)
{
Guid reference = Guid.NewGuid();
string extension = Path.GetExtension(file.FileName);
string fullName= reference.ToString()+extension;
var path = Path.Combine(Server.MapPath("~/Content/TempFiles/"), fullName);
var data = new byte[file.ContentLength];
file.InputStream.Read(data, 0, file.ContentLength);
using (var sw = new FileStream(path, FileMode.Create))
{
sw.Write(data, 0, data.Length);
}
return Content(reference);
}
summary
The first solution is quick and easy if you encounter with a few of this requirement case in your project, but if you encounter with a lot number of this case I recommend you to use second solution.The second solution is so time-consuming but very useful for applications that lots deal with file.

uploading multiple files with ng-file-upload

I am trying to upload multiple files using ng-file-upload and I just can't seem to get it to work.
My html is
<input ngf-select ng-model="files" ngf-multiple="true" id="files" name="files" type="file" value="Choose File(s)" />
and a button once the files have been added
<button ng-click="uploadFiles(files)">Upload</button>
My controller is similar to the examples provided on github and jsfiddle.
$scope.uploadFiles = function (files) {
if (files && files.length) {
angular.forEach(files, function (file) {
$log.warn("counter");
if (files && !file.$error) {
file.upload = Upload.upload({
url: "FileUpload.ashx",
file: file,
fields: {
FormInstanceGuid: $scope.model.FormInstanceGuid,
FormName: $scope.model.Template.Name
}
});
file.upload.then(function (response) {
$log.info("We have succeeded in our call!");
$log.info(response);
}, function (reason) {
$log.info("We have failed in our call!");
$log.info(reason);
});
}
});
My problem comes down to the fact that the UploadHandler (on the server) is only called once and there is only ever 1 file coming in. My thinking is that it should be called once for each file as it's inside a forEach loop.
if (context.Request.Files.Count > 0) //This is never greater than 1
{
HttpFileCollection SelectedFiles = context.Request.Files;
for (int i = 0; i < SelectedFiles.Count; i++) {
HttpPostedFile file = SelectedFiles[i];
}
}
I've checked the network tab, and each file is in its own POST.

using ffmpeg in asp.net razor (C#)

I know questions like this are all over the internet but I believe my case is different, I have a ASP.NET Webpage (Razor C#) and I have a whole video sharing website ready BUT I still don't understand, How can I convert videos to mp4 and webm using ffmpeg on the upload page and instead of having the original saved and added to the database i want the converted version added. heres my upload page code:
#{
WebSecurity.RequireAuthenticatedUser();
var db = Database.Open("PhotoGallery");
var fileName = "";
var uploader = WebSecurity.CurrentUserId;
var date = DateTime.Now.Date;
var extention = "";
if(IsPost){
var numFiles = Request.Files.Count;
if(numFiles <= 0){
ModelState.AddError("fileUpload", "Please specify at least one photo to upload.");
}
else{
var fileSavePath = "";
var uploadedFile = Request.Files[0];
fileName = Path.GetFileNameWithoutExtension(uploadedFile.FileName).Trim();
extention = Path.GetExtension(uploadedFile.FileName).Trim();
string ndom = Path.GetRandomFileName();
var none = ndom.Remove(ndom.Length - 4);
fileSavePath = Server.MapPath("~/Images/userpics/" +
none + extention);
uploadedFile.SaveAs(fileSavePath);
var insertCommand = "INSERT INTO Videos (FileTitle, UploadDate, UserId, ext, Name) Values(#0, #1, #2, #3, #4)";
db.Execute(insertCommand, fileName, date, uploader, extention, none + extention);
Response.Redirect(Href("~/Photo/View", db.GetLastInsertId()));
}
}
}
<h1>Upload Video</h1>
<form method="post" enctype="multipart/form-data">
#Html.ValidationSummary("Unable to upload:")
<fieldset class="no-legend">
<legend>Upload Photo</legend>
#FileUpload.GetHtml(addText: "Add more files", uploadText: "Upload", includeFormTag: false)
<p class="form-actions">
<input type="submit" value="Upload" title="Upload photo" />
</p>
</fieldset>
</form>
<p class="message info">
The maximum file size is 50MB.
</p>
I think your best bet will be to take the upload as-is, and have an offline application or service poll your table for new records and convert them then. When finished, it would update the table with the new file name and a flag indicating it was converted.
I had a similar project and this is what I did.
It's probably not a good idea to try converting these on the fly. If you a fair amount of simultaneous uploads/conversions, you could end up cratering your server.

Uploading File Using jQuery Submit Method

I have a Html Form with several FileUpload elements, which I want to submit it with jQuery submit method, The problem is when the Form submitted It does not send those Files which I want to upload. I don't know what is the problem and How should I solve that. The following code shows what is going on my code:
#using (Html.BeginForm("Create", "Personel", new { #enctype = "multipart/form-data" }))
{
<input type="file" id="personelPhoto" name="personelPhoto" />
}
if (form["personelPhoto"] != null)
{
// Request's files count is 0
}
Any advice will be helpful.
If you use a generic form submit and have the below as your backend c#(4.0) code it should work
if (Request.Files.Count > 0)
{
for (int i = 0; i < Request.Files.Count; i++)
{
HttpPostedFileBase hpfTest = Request.Files[i] as HttpPostedFileBase;
if (hpfTest.ContentLength == 0)
continue;
string savedFileName = Path.Combine(Server.MapPath("~") + "\\Files\\",Request.Form["name"]);
hpfTest.SaveAs(savedFileName);
}
}
Or you could use the "HttpFileCollection" in other versions of .net
HttpFileCollection files = Context.Request.Files;
files[0].SaveAs();

Categories