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.
Related
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;
}
Consider the following code snippet
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(MyViewModel viewModel)
{
if (ModelState.IsValid)
{
//map properties here
using (var context = new MyEntities())
{
context.Users.Add(user);
context.SaveChanges();
}
if (Request.Files.Count > 0)
{
foreach (string fileName in Request.Files)
{
HttpPostedFileBase file = Request.Files[fileName];
if (file != null && file.ContentLength > 0)
{
//do checks and upload file here
}
}
}
}
return RedirectToAction("Index", "Home");
}
The form can be submitted as a standalone or with files which then get uploaded to a server. Now my issue is If I submit the form without any files or just one file then everything works as expected. However users can upload more than one file at a time and that's where the problem comes in. The files get uploaded but I get more than one entry in the database for that particular form. For example if the user uploads three files I'll get three entries in the database exactly that same.
So my question is how do I get around this?
On the client side I'm using DropZoneJs and calling the method as
<script>
Dropzone.autoDiscover = false;
var myDropZone = new Dropzone("#dzUpload", {
url: "/Home/Create",
autoProcessQueue: false,
previewsContainer: ".preview",
});
$("#submit-all").attr("type", "button").on('click', function (e) {
e.preventDefault();
e.stopPropagation();
if (myDropZone.getQueuedFiles().length > 0) {
myDropZone.options.autoProcessQueue = true;
myDropZone.processQueue();
}
else {
$("#dzUpload").submit();
}
});
</script>
I've also come across this question but I still have the same issue
It looks like the uploadMultiple option will change the behavior so only one request is sent to the server.
var myDropZone = new Dropzone("#dzUpload", {
url: "/Home/Create",
autoProcessQueue: false,
previewsContainer: ".preview",
uploadMultiple: true,
});
So if I am right the plugin will post the form for every file you drop into your plugin right?? One way is to generate a a GUID and maintain it in your form hidden input. So every time your plugin posts it will post this GUID as well. So change your insert statement into a upsert ( update or insert) based on the Guid.. You must save this GUID also along with your other data..
So every time you intend to insert check if the GUID already exist If so update it else insert new record.
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();
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");
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.