Uploading File Using jQuery Submit Method - c#

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();

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 upload multiple files into C# and loop through them in MVC

I'm having a problem with uploading multiple files to C# and loop through them. I found a question with a similar problem but nobody answered it.
I upload multiple files through an html input. The file count passes through to my controller with the correct amount relative to the amount of files I selected. However when I try to loop through each of my files it loops through the first file relative to the file count. For example if I upload 3 files it loops through the first file 3 times or if I upload 5 files it loops through the first file 5 times. It should not do this. I want it to loop through each file individually. Please help!!! here is my code:
Razor View(I'm using a bootstrap library for fileinputs called bootstrap-filestyle):
#using (Html.BeginForm("Initial", "DataCapture", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
<h4>Select files</h4>
<input type="file" multiple="multiple" id="fileToUpload" name="file">
</div>
<div>
<input type="submit" value="Capture" class="btn btn-default" />
</div>
}
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Initial(ClaimModel claimModel)
{
if (ModelState.IsValid)
{
//OtherCode
handleFile(Request.Files, c.ClaimID);
return RedirectToAction("Index", "ClaimFiles", new { id = c.ClaimID });
}
//OtherCode
}
private void handleFile(HttpFileCollectionBase Files, int ClaimID)
{
foreach (string fileName in Files)
{
HttpPostedFileBase file = Request.Files[fileName];
//OtherCode
}
//OtherCode
}
I put break points on handleFile(Request.Files, c.ClaimID); and inside foreach (string fileName in Files){...}. As I said it correctly passes through the file count if I upload 3, 4, 5 or any amount of files however it only loops through the first file that amount of times and returns the first file multiple times as well. I need it to loop through and return each file individually. How do I do this correctly?
Use Request from server, here is one example:
for (int i = 0; i < Request.Files.Count; i++)
{
var fileDoc = Request.Files[i];
}
Or you can try something like this:
HttpPostedFileBase hpf = null;
foreach (string file in Request.Files)
{
hpf = Request.Files[file] as HttpPostedFileBase;
}

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.

Validate File size before upload

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");

Upload multiple files using HttpFileCollectionBase issue with C# and MVC3

I created a controller which save files.
The below code is a part of that Controller:
if ( Request.Files.Count != 0 ) {
HttpFileCollectionBase files = Request.Files;
foreach ( HttpPostedFileBase file in files ) {
if ( file.ContentLength > 0 ) {
if ( !file.ContentType.Equals( "image/vnd.dwg" ) ) {
return RedirectToAction( "List" );
}
}
}
}
in ASPX page is simple:
<input type="file" name="file" />
<input type="file" name="file" />
...// many inputs type file
The problem is foreach because it returns an error like (I know because I run in Debug mode and placed breakpoint at foreach statement):
Unable to cast object of type 'System.String' to type 'System.Web.HttpPostedFileBase'.
What is my mistake ?
Try like this:
[HttpPost]
public ActionResult Upload(IEnumerable<HttpPostedFileBase> files)
{
if (files != null && files.Count() > 0)
{
foreach (var uploadedFile in files)
{
if (uploadedFile.ContentType != "image/vnd.dwg")
{
return RedirectToAction("List");
}
var appData = Server.MapPath("~/app_data");
var filename = Path.Combine(appData, Path.GetFileName(uploadedFile.FileName));
uploadedFile.SaveAs(filename);
}
}
return RedirectToAction("Success");
}
and modify the markup so that the file inputs are named files:
<input type="file" name="files" />
<input type="file" name="files" />
...// many inputs type file
for (int i = 0; i < Request.Files.Count; i++)
{
var file = Request.Files[i];
// this file's Type is HttpPostedFileBase which is in memory
}
HttpRequestBase.Files requires an index, so use for instead of foreach.
Have a look at this post by Phil Haack which demonstrates how to process multiple file uploads using MVC. The object you are trying to use is for ASP.NET Webforms.

Categories