How to handle multiple image uploads - c#

I'm working on a ASP.NET MVC site that will allow a user to upload multiple images to a gallery. After a user uploads their images and before they are saved to the database, the user will have the ability to reorder the images using a jQuery drag and drop. The user can then submit their uploads. The user will also have the ability later on to edit their gallery and again have the ability to reshuffle the order of their images. I will not be saving the images to the database, just the filenames. I'm not sure how to best handle this. I'm thinking the POST controller will take a List<HttpPostedFileBase> parameter, and then convert to a byte [] array to maintain the image order. Then save the image names to the database as a comma separated string? What would the most efficient way to handle this be?

Alright so if we put drag and drop a side, see this as your view:
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="files" value="" multiple="multiple"/>
<input type="submit" value="Upload"/>
}
In your controller:
[HttpPost]
public ActionResult Index(HttpPostedFileBase[] files)
{
try
{
foreach (HttpPostedFileBase file in files)
{
string name = System.IO.Path.GetFileName(file.FileName);
file.SaveAs(Server.MapPath("~/Images/" + name));
string filename = "Images/" + name;
//Save the the filename to your database
}
}
catch
{
throw ex;
}
return View();
}

Related

Uploading more than one file in Razor Pages .NET 6 - empty form submission

I build my form dynamically to allow multiple images to be uploaded, as per resolution requirements.
The RequiredDimensionsOptions collection has image requirements, eg. 1296x450, 916x450, etc. I loop through these and render a File upload control for each, thusly (abbreviated) - with a unique ID for each:
<form enctype="multipart/form-data" method="post" id="uploadFiles">
#foreach (var requiredDimension in Model.RequiredDimensionsOptions)
{ // the ID will be something like "file-0000w0000h"
<p>
<label for="file-#(requiredDimension.Width)w#(requiredDimension.Height)h">#requiredDimension.Width x #requiredDimension.Height</label>
<input class="forceLeftMargin" id="file-#(requiredDimension.Width)w#(requiredDimension.Height)h" name="file-#(requiredDimension.Width)w#(requiredDimension.Height)h" type="file">
</p>
}
<input type="submit" value="Upload files"/>
</form>
I can then get the files using some C#:
public async Task<IActionResult> OnPostAsync()
{
foreach (IFormFile? file in Request.Form.Files) // Request.Form.Files is empty when I set more than 1 upload control with a file
{
// work with the uploaded files
}
}
The problem is that when I try to upload more than one file using the controls, the files do not appear in the Request.Form collection as files or even as submitted fields. So this:
Request.Form.Keys.Any(q=>q.StartsWith("file-"))
... resolves to false. I have the single AntiForgeryRequestToken element. When I upload a single file, it works fine.
How can I have multiple files uploaded?
I appreciate I could use a multiple-file upload option, but I want to maintain the resolutions for validation and user experience.
This May help or give a closer solution:
in razor page .cshtml File.
#page
#model KafilWepAdmin.Pages.testingModel
#{
var RequiredDimensionsOptions = new Dictionary<int, int>() { {1296, 450 }, { 916, 450 } };
}
<form method="post" enctype="multipart/form-data">
#foreach (var requiredDimension in #RequiredDimensionsOptions)
{
<div>
<label for=$"w{#requiredDimension.Key}h{#requiredDimension.Value}">#requiredDimension.Key x #requiredDimension.Value</label>
<input type="file" class="forceLeftMargin" id=$"w{#requiredDimension.Key}h{#requiredDimension.Value}" name=$"w{#requiredDimension.Key}h{#requiredDimension.Value}">
</div>
}
<button type="submit" asp-page-handler="GetFiles">Upload Files</button>
</form>
in .cs File
public async Task<IActionResult> OnPostGetFilesAsync()
{
var files = Request.Form.Files;
foreach (var file in files)
{
// process the file
}
return Page();
}

Multi file upload in ASP.NET using c#

I have a button on my website where users can upload multiple files onto the site. For some reason, in my controller the "file" variable always gets the value of NULL. I am able to upload files as a user, but my controller doesn't read that in for some reason. I'm not sure why and any guidance to the right direction would be greatly appreciated !
This is my cshtml:
<p id="FileArea"></p>
<input id="Files" name="Files" type="file" multiple="multiple" />
This is my model:
public IEnumerable<HttpPostedFileBase> Files { get; set; }
This is my controller:
foreach (var file in viewModel.Candidate.Files)
{
var file_s = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/Files/location", file_s);
file_s.SaveAs(path);
}

MVC: How to get full file path from file input field? [duplicate]

This question already has answers here:
How to get full path of selected file on change of <input type=‘file’> using javascript, jquery-ajax?
(14 answers)
Closed 6 years ago.
I have the following razor code:
<div class="container">
#Html.ValidationSummary(false)
#using (Html.BeginForm("EncryptFile", "Encryption", new { returnUrl = Request.Url.AbsoluteUri }, FormMethod.Post, new { #id = "encryptionform", #class = "form-horizontal" }))
{
<div class="form-group">
#Html.Label("File", new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input type="file" id="encryptfilefield" name="uploadedfile" enctype='multipart/form-data'/>
</div>
</div>
<button type="submit" id="encryptfilebutton">Encrypt</button>
<button id="decryptfilebutton" type="button">Decrypt</button>
<button id="reencryptfilebutton" type="button">Re-Encrypt</button>
}
</div>
and the following controller code gets called when I click the Encrypt button:
[HttpPost]
public ActionResult EncryptFile(string uploadedfile)
{
/*process the file without uploading*/
return Json(new { status = "success", message = "Encrypted!" });
}
I am able to hit this action when I click the encrypt button, but the uploadedfile string always comes in as null. How can I get the fill filepath of the file that was selected? Please note that I am not trying to upload it to the server (despite "uploaded" appearing in the name), I just need the filepath.
EDIT
I saw in IE 11 that the following showed the file path fully (the part inside the alert):
alert($("#encryptfilefield").val());
However this is not a full solution, and it seems there is no solution due to to it being a security issue.
Thank you.
Updated Answer
Unfortunately there's no way to get that info consistently among all browsers., there's multiple posts on here about this topic and the conclusion is browsers don't allow it for security purposes.
I did find that in IE 11 they do include the path within the input dom element .value property, but I don't know if that works in other versions, and it does not work in chrome.
$('input[type=file]').change(function () {
console.dir(this.value);
console.dir(this.files[0])
})
Unfortunately that's about the best you can expect. Here's a post that has a couple things you could do to possibly achieve some very specific scenarios.
How to get full path of selected file on change of <input type=‘file’> using javascript, jquery-ajax?
Original Answer (how to get file path "After" it reaches server)
The null param issue I'm thinking is because MVC binds on element name property.
<input type="file" id="encryptfilefield" name="uploadedfile" enctype='multipart/form-data'/>
and your controller action is marked as type string, which is not what your input type is.
you could either change that to this,
[HttpPost]
public ActionResult EncryptFile(HttpPostedFileBase uploadedfile)
{
or try grabbing the file straight from the Request object like below, you'd have to save it somewhere before you get the full path of it though, i don't believe you'll get the filepath of where it originated from, only after you save it.
[HttpPost]
public ActionResult EncryptFile(string uploadedfile)
{
HttpPostedFileBase myfile = Request.Files[0];
if (file.ContentLength > 0)
{
// extract only the fielname
var fileName = Path.GetFileName(file.FileName);
// store the file inside ~/App_Data/uploads folder
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"),fileName);
file.SaveAs(path);
}
/*process the file without uploading*/
return Json(new { status = "success", message = "Encrypted!" });
}

Display a picture uploaded to the server

I am trying to create a user profile picture in a ASP MVC5 project. I have added a page that is called changepicture.cshtml and will display the current user's picture.
I have an upload function that will take a picture someone uploads like hank.jpg and rename it to that users_id.jpg.
For example:
System.Data.Entity.DynamicProxies.ApplicationUser_9C8230B38B954135385F2B0311EAC02ED8B95C4D504F8424BA3ED79B37F0AAAF.jpg
I would like to display each users individual picture in the page by grabbing there user id and adding .jpg, how would I do this?
changepicture.cshtml
#model KidRoutineLogging.Models.ChangePictureViewModel
#{
ViewBag.Title = "Change Picture";
}
<h2>#ViewBag.Title.</h2>
<h4>Your Current Picture : #Html.ViewBag.CurrentPicture</h4>
<img src="#Url.Content("~/uploads/hank.jpg")" />
<br />
<br />
#using (Html.BeginForm("", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="FileUpload1" /><br />
<input type="submit" name="Submit" id="Submit" value="Upload" />
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
HomeController.cs
public async Task<ActionResult> Index()
{
foreach (string upload in Request.Files)
{
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
string path = AppDomain.CurrentDomain.BaseDirectory + "uploads/";
//string filename = Path.GetFileName(Request.Files[upload].FileName);
//Request.Files[upload].SaveAs(Path.Combine(path, filename));
Request.Files[upload].SaveAs(Path.Combine(path, user + ".jpg"));
}
return View();
}
You are getting a funky-typed name for your file because you are attempting to cast an entire class (object) to string. Additionally, if you are wanting to name the file "UserId.jpg", your code is doing more work than it should.
This line:
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
Can be simplified to this line:
var userId = User.Identity.GetUserId();
That would leave your final code as:
public async Task<ActionResult> Index()
{
foreach (string upload in Request.Files)
{
var userId = User.Identity.GetUserId();
string path = AppDomain.CurrentDomain.BaseDirectory + "uploads/";
Request.Files[upload].SaveAs(Path.Combine(path, userId + ".jpg"));
}
return View();
}
You could get rid of the userId variable completely, and update your SaveAs method to
Request.Files[upload].SaveAs(Path.Combine(path, User.Identity.GetUserId()+ ".jpg"));
Also - you really should decorate this ActionResult with the <HttpPost> attribute since it should only be handling the POSTing of the form and not associated with a GET request.

Add File Upload Control in asp.net mobile website?

Currently, I'm working on asp.net mobile website and I've to implement one functionality related to upload file in mobile website.
I'm using asp:upload Control but, It's not working in mobile website.
I have been searching in google for this issue since last week, But I can't find any relative source or blog.
Can anyone help me on this topic?
In view:
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" />
<input type="submit" value="OK" />
}
In Control:
[HttpPost]
public ActionResult Index(HttpPostedFileBase file)
{
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
// extract only the fielname
var fileName = Path.GetFileName(file.FileName);
// store the file inside ~/App_Data/uploads folder
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(path);
}
// redirect back to the index action to show the form once again
return RedirectToAction("Index");
}
and remove the jquerymobile script from your page. Like in MVC4
#Scripts.Render("~/bundles/jquery", "~/bundles/jquerymobile")
Remove this line, it's the source of the conflict.

Categories