C# MVC HTML5 file upload control with multiple attribute duplicates images - c#

I am having a strange issue with HTML5 file upload control with multiple attribute. I have no clue about how to fix it. I am trying to explain the problem below:
When uploading multiple images on the server, the images are uploading but some of them are getting duplicated, not by name, but by image itself.
Means if I select say 10 images, I can see 10 images are uploaded with different names (names are generated dynamically) but say 4 images are exactly the same. Means, 6 out of 10 selected images uploaded perfectly, but 4 original images got disappeared completely! But these 4 images are using contents from 6 images uploaded correctly. Moreover, this is happening in random. There is no order or sequence from what I can understand what will disappear and what will re-uploaded with a different name.
In short:
Selected 10 different images for upload
Number of images uploaded is 10
6 images (say) uploaded with correct content
4 images (say) uploaded with correct file name, but content is wrong. They are using contents of 6 images and original content of these images simply disappeared.
This is happening when I am selecting more than 5 images for upload. Anything less than 6 has no problem.
Now when I test the same code at local development environment this is not happening at all! I checked folder permission on the server and there is no restriction imposed.
I am not sure whether I could explain the issue correctly because it is really a typical one and I never encountered similar thing before !!
Markup:
<div class="row gapp-10 medium">
<div class="col-md-9">
Upload Photos <span class="small-font gray-text">(Optional)</span> <span class="small-font red-text">
(Combined upload size can't exceed 10mb.)</span>
<%:Html.TextBoxFor(model => model.VehicleImages, new {#type="file", #id="fUpload", #multiple="multiple", #class="btn btn-clc-theme-orange"}) %>
</div>
<div class="clearfix"></div>
</div>
Controller Action method:
[Authorize]
[HttpPost]
public ActionResult Upload(VehicleViewModel model)
{
if (ModelState.IsValid)
{
_service = new VehicleService();
model.SellerId = CommonMethods.LoggedInUser.SellerId;
var newVehicle = _service.Save(model);
newVehicleId = newVehicle.VehilceId;
for (var i = 0; i < Request.Files.Count; i++)
{
var fl = Request.Files[i];
if (fl == null || fl.ContentLength <= 0) continue;
var filename = System.IO.Path.GetFileName(fl.FileName.Trim());
if (string.IsNullOrEmpty(filename)) continue;
var fileExtension = System.IO.Path.GetExtension(filename);
var newFileName = String.Concat(DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture), fileExtension);
System.IO.Directory.CreateDirectory(Server.MapPath("~/VehiclePhoto/" + newVehicleId));
var photoPath = System.IO.Path.Combine(Server.MapPath("~/VehiclePhoto/" + newVehicleId + "/"), newFileName);
fl.SaveAs(photoPath);
}
}
return RedirectToAction("VehicleUploaded");
}
Edit
This is how the upload control is placed inside the form element and the method is being called. Nothing fancy, just the simple and classical way.
<% using(Html.BeginForm("Upload", "VehicleUpload", FormMethod.Post, new {enctype = "multipart/form-data"}))
{ %>
...
<div class="row gapp-10 medium">
<div class="col-md-9">
Upload Photos <span class="small-font gray-text">(Optional)</span>
<span class="small-font red-text">(Combined upload size can't exceed 10mb.)</span>
<%:Html.TextBoxFor(model => model.VehicleImages, new {#type="file", #id="fUpload", #multiple="multiple", #class="btn btn-clc-theme-orange"}) %>
</div>
<div class="clearfix"></div>
</div>
...
<input type="submit" value="Upload Vehicle" class="btn btn-primary" />
<% } %>

Related

How to use file upload?

My fileupload isn't working. I get this error each time I try: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index.
I'm doing all of this from the .cshtml file because, the previous web master deleted all of the source code when he was fired. So I only have the deployed files to work with and none of the controllers and models. I also cannot add any new functionality to the website.
I used this tutorial this tutorial following the single file upload.
Here is my code:
#using Microsoft.Web.Helpers;
#{
Layout="~/Views/Shared/_FUllWidthLayout.cshtml";
var message="";
if(IsPost){
if(Request.Files.Count > 0){ //<-- If more than 0 files, FAILS HERE
try{
var uploadedFile = Request.Files[0]; //<-- FAILS HERE
var fileName = Path.GetFileName(uploadedFile.FileName);
var fileSavePath = Server.MapPath("~/Documents/Jobs/" + fileName);
uploadedFile.SaveAs(fileSavePath);
message = Request.Files.Count + " files uploaded to " + fileSavePath;
}
catch(Exception e){
message = e.Message;
}
}else{
message = Request.Files.Count + " files uploaded.";
}
}
}
And my HTML:
<form id="uploadForm" method="post" enctype="multipart/form-data">
<h3>FileUpload - Single-File Example</h3>
<div class="inline-div">
#FileUpload.GetHtml(
initialNumberOfFiles:1,
allowMoreFilesToBeAdded:false,
includeFormTag:true,
uploadText:"Upload")
<small class="red">#message</small>
</div>
</form>
I also tried taking the FileUpload control out of the form like this:
<h3>FileUpload - Single-File Example</h3>
<div class="inline-div">
#FileUpload.GetHtml(
initialNumberOfFiles:1,
allowMoreFilesToBeAdded:false,
includeFormTag:true,
uploadText:"Upload")
<small class="red">#message</small>
</div>
Message says "0 files uploaded." as seen here:
Can anyone point out what I'm doing wrong and how I can fix it? Or is there another tool I can use to do the same work?

How to populate check boxes in a pdf with data from SQL in asp.net core, c#

So am working on this .Net core project (I am still a beginner). The project aims to print out a populated/filled pdf form with data from Sql. I have managed to fill part of the pdf with data other that the checked boxes. This is giving me hell. The input type = 'text' fills alright, when I print the form... But the checked boxes(input type ='checkbox') are empty... And I don't know what else to do
I have tried looking around to no avail. I can't get resources... Could someone point me to the right direction, or show me how to do it. Below is my code PrintController.cs for populating the form fields
public string GetHtml(string clientId)
{
var customerData = (from t in _context.ClientProfile
where t.FormattedId == clientId select t
);
var sb = new System.Text.StringBuilder();
foreach (var c in customerData
{
sb.AppendFormat(#"
<div class='header'>
<div class='container'>
<div class='header-top'>
<p>File no: {0}</p>
</div>
</div>
</div>
<div class='form-area'>
<div class='container'>
<label> Name Of facility: </label> <input type = 'text' value = {1}/>
<label> Delivery Point: </label> <input type = 'text' value ={2}/>
</div>
</div>", c.FormattedId, c.FacilityCode, c.EntryPoint);
}
}
So the above works well with text input, but nothing shows with checkbox input type....

File upload drag and drop with dropzone.js

I'm using dropzone.js to implement a drag and drop feature to upload a file. And it's working. What I don't understand is why I can't make it to limit the filesize and the file extension. I have the code for it, I think, but it just won't do it.
In the cshtml page:
<script src="~/js/dropzone.js"></script>
<link href="~/css/dropzone.css" rel="stylesheet" />
<script>
Dropzone.options.dropzone = {
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 2, // MB
acceptedFiles: ".png,.jpg,.gif,.bmp,.jpeg",
accept: function (file, done) {
if (file.name == "justinbieber.jpg") {
done("Naha, you don't.");
}
else { done(); }
}
};
</script>
<div class="row">
<div class="col-md-9">
<div id="dropzone">
<form action="Upload" class="dropzone needsclick dz-clickable" id="uploader">
<div class="dz-message needsclick">
Drop files here or click to upload.<br>
</div>
</form>
</div>
</div>
</div>
And in the HomeController
[HttpPost]
public async Task<IActionResult> Upload(IFormFile file)
{
var uploads = Path.Combine(_environment.WebRootPath, "images");
if (file.Length > 0)
using (var fileStream = new FileStream(Path.Combine(uploads, file.FileName), FileMode.Create))
await file.CopyToAsync(fileStream);
return RedirectToAction("About");
}
I mean, the code is given by them, I have the dropzone.js and the dropzone.css like they tell us to do and still... The thing is, it's working. It uploads, goes to the code behind. Everything. I just can't apply those limitations, even though they are there...
Does anyone have an idea of what's going on here?
You've set the options on a different Dropzone than the form. From the docs:
Dropzone will find all form elements with the class dropzone, automatically attach itself to it, and upload files dropped into it to the specified action attribute.
So your <form>, with class dropzone, is automatically set up as a Dropzone.
Again from the docs, to set options on a Dropzone, you use Dropzone.options.myAwesomeDropzone = {}, where:
// "myAwesomeDropzone" is the camelized version of the HTML element's ID
In your code, you're using Dropzone.options.dropzone, so you're applying those options to a Dropzone with id dropzone. In your HTML, that's a <div>, not your existing <form> Dropzone. So when you drop a file onto your <form>, those options you've specified are not relevant - they're for a different Dropzone (which is actually never instantiated)!
Get rid of your <div id="dropzone">, and change the identifier on your options to Dropzone.options.uploader, so they apply to your form Dropzone.

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;
}

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.

Categories