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?
Related
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.
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" />
<% } %>
I am receiving the following error in ASP.NET MVC. "the following sections have been defined but have not been rendered for the layout page" - Now I know what the error is about, but can't figure a way around it in fact it probably should work but I don't know why it won't.
I have an index.cshtml page which renders all dynamically driven DB content. Pages can contain widgets (Reusable blocks on content). The index.cshtml code is below:
#{
Layout = AppSettings.LayoutFileDirectory + "/" + PageDAL.GetLayoutFileForPage(Model.Page);
string currentSection = string.Empty;
}
#if(!string.IsNullOrEmpty(Model.Page.PageTitle))
{
<h3>#Model.Page.PageTitle</h3>
}
#Html.Raw(Model.Page.PageText)
#foreach (var item in Model.Page.WidgetsInPages)
{
//if(IsSectionDefined(item.WidgetSection))
//{
string sectionName = item.WidgetSection;
//don't want to redefine section
if (currentSection!= sectionName)
{
DefineSection(sectionName, () =>
{
//render all this sections widgets
foreach (var insider in Model.Page.WidgetsInPages.Where(w => w.WidgetSection == sectionName).OrderBy(w => w.WidgetSortOrder))
{
if (insider.Widget.WidgetFile != null)
{
Write(Html.Partial(AppSettings.WidgetTemplatesDirectory + "/" + insider.Widget.WidgetFile, item.Widget));
//Write(Html.Partial(AppSettings.WidgetTemplatesDirectory + "/" + insider.Widget.WidgetFile, new {Widget=item.Widget}));
}
}
});
currentSection = sectionName;
}
//}
}
Now I have a _DefaultTheme.cshtml with the following sections. (This is the primary layout page)
<div class="header">
#RenderSection("_HeaderSection", false)
</div>
<div class="container">
#RenderSection("_AboveBodySection", false)
#RenderBody()
#RenderSection("_BelowBodySection", false)
</div>
#RenderSection("_AfterBodySection", false)
<footer class="footer">
<div class="container">
#RenderSection("_FooterSection",false)
#Html.Raw(FrontEnd.PopulateFooter(Model.Website))
</div>
</footer>
Adding widgets to the any page which has the _DefaultTheme layout works perfectly fine, but when I start inheriting pages it becomes an issue. I now have another page _DefaultThemeArticles.cshtml the master page is _DefaultTheme.cshtml
The _DefaultThemeArticles.cshtml contains this:
#{
Layout = "~/Themes/_DefaultTheme.cshtml";
}
<div class="container">
#RenderBody()
</div>
Now the error occurs when adding Widgets to any page which has this layout. I get this error:
The following sections have been defined but have not been rendered for the layout page "~/Themes/_DefaultThemeArticles.cshtml": "_BelowBodySection".
But the section _BelowBodySection has been defined in the master page, why would it not work here?.
The problem is that in your layout page, _DefaultTheme.cshtml, by writing all of these:
#RenderSection("_HeaderSection", false)
#RenderSection("_AboveBodySection", false)
#RenderSection("_BelowBodySection", false)
#RenderSection("_AfterBodySection", false)
#RenderSection("_FooterSection",false)
You are asserting that in any child page, like _DefaultThemeArticles, there must be a section defined for each of the above. If Razor doesn't find a particular section defined (in your case _BelowBodySection) in the child page, it throws the error. You can use the following Razor to solve this:
#if (IsSectionDefined("_BelowBodySection"))
{
#RenderSection("_BelowBodySection")
}
This will only render the section if it exists.
Hope this helps.
I can't find an existing answer so far, but here is my goal:
I'd like to use the asp.net fileupload control(or some other control you might suggest) to select a series of files. WITHOUT submitting a form, i'd like the selected files to be displayed in a concatenated list of some sort.
Is this possible with the Fileupload control or do I have to use something else? I've seen many answers involving submission then grabbing the filenames, but I don't want to take a trip to the server for that. Just looking to grab the filenames when they're selected, all clientside.
Thank you for your time!
Using files property. See the code below:
function onInputChange(e) {
var res = "";
for (var i = 0; i < $("#customInput").get(0).files.length; i++) {
res += $("#customInput").get(0).files[i].name + "<br />";
}
$('#result').html(res);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="customInput" type="file" accept="image/*" multiple onchange="onInputChange(event)" />
<br /><br />
<div style="color:blue" id='result'></div>
try this -
Javascript
function showFile() {
var file = document.getElementById("<%=FileUpload1.ClientID%>");
var path = file.value;
alert(path);
}
File Upload Control
<asp:FileUpload ID="FileUpload1" runat="server" onchange="showFile()" />
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.