Im trying to upload a picture in a MVC app build on .net
I made a button :
#Html.EditorFor(model => model.Imagen,
new { htmlAttributes = new{ #class = "input", #type="file" } })
But it only gets the name of the picture. I read thats because of security reasons, so what is the simplest way of get the full path of my picture?
I can use anything (.net framework)
The uploaded file doesn't have a path until you save it somewhere. Your Action should receive an HttpPostedFileBase object from the post which you can use to do this.
A simple example:
[HttpPost]
public JsonResult Upload(HttpPostedFileBase upload)
{
var filePath = System.IO.Path.Combine(#"C:\uploads\", upload.FileName);
upload.SaveAs(filePath);
}
Related
If I want upload a file it's simply:
Razor
#Html.TextBoxFor(m => m.File, new { type = "file" })
or
Html
<input type="file">
But, If I want select a folder to upload all files than contains, is it possible?
Something like:
Razor
#Html.TextBoxFor(m => m.Folder, new { type = "folder" })
Showing a "select folder dialog".
You can't do that when using #Html.TextBoxFor. There may be another way to upload a folder, but I don't know of it.
However, you can change the file upload dialog to upload multiple files at once, which is essentially the same thing. Here is a tutorial showing how.
Essentially, you need to add the following attribute to your file upload input:
#Html.TextBoxFor(m => m.File, new { type = "file", #multiple = "multiple" })
You also need to add the multpart/form-data attribute to your Razor code to generate the form. Here is an example from that tutorial:
#using (Html.BeginForm("UploadFiles", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
At this point, you can select multiple files to upload. You can easily open the folder, hit CTRL+A to select all, then hit upload to upload the entire folder at once.
Please note that you'll need to modify the controller action to accept multiple files at once.
EDIT: Here is an example on how to handle this in your controller action, from the previously mentioned tutorial. Note that your parameter is an array of HttpPostedFileBase objects, each one representing a file you upload. Then, you iterate through each and save it.
[HttpPost]
public ActionResult UploadFiles(HttpPostedFileBase[] files)
{
//Ensure model state is valid
if (ModelState.IsValid)
{ //iterating through multiple file collection
foreach (HttpPostedFileBase file in files)
{
//Checking file is available to save.
if (file != null)
{
var InputFileName = Path.GetFileName(file.FileName);
var ServerSavePath = Path.Combine(Server.MapPath("~/UploadedFiles/") + InputFileName);
//Save file to server folder
file.SaveAs(ServerSavePath);
}
}
}
return View();
}
I have a byte[] stored in a VARBINARY(MAX) column in a table in my database.
I want to show this image on my index.cshtml page - but I'm stuck.
My CSHTML looks like this:
#using Microsoft.AspNetCore.Hosting.Internal
#{
ViewData["Title"] = "Title";
}
<h2>#ViewData["Title"]</h2>
<h3>#ViewData["Message"]</h3>
#if (!Context.User.Identity.IsAuthenticated)
{
<p>blah blah.</p>
<p>blah blah</p>
}
#if (Context.User.Identity.IsAuthenticated)
{
<p>Hi #(Context.User.Identity.Name)<br/></p>
<p>Where we off to today?</p>
}
I want to add
<img src="...." />
obviously I don't know what to do here.
My model has the byte array data:
public byte[] UserImage { get; set; }
My controller assigned that the value:
var model = new IndexViewModel
{
Username = user.UserName,
Email = user.Email,
PhoneNumber = user.PhoneNumber,
IsEmailConfirmed = user.EmailConfirmed,
StatusMessage = StatusMessage,
UserImage = user.UserImage
};
but I am using .net core in VS2017 and the answers I have found don't seem to work for me. Any help would be really appreciated.
Thanks
Johan
You have two options:
Base64 encode the byte[] and use a Data URI:
<img src="data:image/png;base64,[base64-encoded byte array here]">
However, bear in mind two things. 1) Data URIs are supported in every modern browser, but notoriously do not work in IE 10 and under. That may not be an issue, but if you need to have legacy IE support, this is a non-starter. 2) Since you're Base64-encoding, the size of the "image" will balloon roughly 50%. As such, Data URIs are best used with small and simple images. If you've got large images or simply a lot of images, your HTML document can become a very large download. Since Data URIs are actually embedded in the HTML code, that means the browser cannot actually begin to render the page at all until the entire HTML document has loaded, which then also means that if it's megabytes in size, your users will be waiting a while.
Create an action that pulls the image from the database and returns it as a FileResult. This is the most optimal path. Essentially, you just need an action that accepts some sort of identifier for the image, which can be used to pull it from the database. You then return the byte[] like:
return File(myByteArray, "image/png");
In your view, you simply make the image source the route to this action:
<img src="#Url.Action("GetImage", "Foo", new { id = myImageIdentifier }">
Ok so I managed to work it out with the help above. I created a method on the controller that looks like this:
public FileResult GetFileFromBytes(byte[] bytesIn)
{
return File(bytesIn, "image/png");
}
[HttpGet]
public async Task<IActionResult> GetUserImageFile()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return null;
}
FileResult imageUserFile = GetFileFromBytes(user.UserImage);
return imageUserFile;
}
in my cshtml I then added this:
<img src= '#Url.Action("GetUserImageFile", "Manage")'/>
"Manage" was the start of the controller name. I didnt need to pass in an ID as my image bytes are stored on the aspuser so the code knows which user it is using the GetUserAsync
Can anyone see problems with this? Also, it doesnt seem to care that the origional image is a jpeg but in the code I am using "image/png", am I risking losing something?
Many thanks for the comments and help! this is such an amazing forum!
I am trying to create a simple post in which I am also attaching an image using Provider Hosted App on Sharepoint online, and I am not able to get SPHostUrl at Controller in HttpContext.Request, I mean SPHostUrl is missing in HttpContext.Request.
[HttpPost]
public ActionResult Contact(SimplePostModel model,HttpPostedFileBase file)
{}
View
#using (Html.BeginForm("Contact","Home",null,FormMethod.Post,new { enctype= "multipart/form-data"}))
The question is if I am sending this part new { enctype= "multipart/form-data"} in the above mentioned statement of View, I am not able to get SPHostUrl parameter in HttpContext.Request.
If I am not sending the html attributes then I am able to get SPHostUrl parameter in HttpContext.Request. and without html attributes I am also not able to upload a file.
Thanks in Advance for your help.
I have solved the issue,by changing some piece of code on in the Razor View.
#using (Html.BeginForm("Contact","Home",null,FormMethod.Post,new { enctype= "multipart/form-data"}))
Instead of null for object route values I send the spHosturl like below.
#using (Html.BeginForm("Contact","Home",new { SPHostUrl = spUrl },FormMethod.Post,new { enctype = "multipart/form-data" }))
the spUrl value comes like below
#{
var spUrl = Request.QueryString["SPHostUrl"];
}
I hope this will help for new sharepoint online developers
I have a gallery website. That developed in asp.net. Now I want to port it to asp.net MVC5. While doing it I run into an issue without solving it I cant go into further development. So here is the requirements:
a) Every gallery has its own independent folder and has photos in it. the url for the photo galleries will be: localhost/gallery1, localhost/gallery2 and so on.
b) Each gallery has two types of layouts and options the commbo is given bellow:
localhost/gallery1/still/grid
localhost/gallery1/still/slide
localhost/gallery1/gifs/grid
localhost/gallery1/gifs/slide
c) change of [gallery1] to any other name should serve the photos from within the new name folder.
d) we also have a way to configure gallery for each folder by accessing admin
localhost/gallery1/admin
localhost/gallery2/admin
I am new to MVC. And I dont know how to work with that... I just created a brand new MVC5 project using Visual Studio with builtin example. Can anyone help me how to deal with this?
EDIT:
The controller has to be a universal control for anything immediately after localhost/ so in my example urls gallery1 and gallery2 or anything like that will be caught by a universal controller, may be GalleryController.
After the name of the gallery, the next two url segments are going to work in conjugation. I am not sure how to catch them in a universal controller and then segment them out on the basis of what is after still and gifs.
I have found answer to my own question. Here is what i did.
Inside RouteConfig.cs I simply added following mapping:-
routes.MapRoute(
name: "Dynamic",
url: "{name}/{action}/{layout}",
defaults:
new {
controller = "Gallery",
action = "Display" ,
layout = UrlParameter.Optional
});
This is how my GalleryController.cs looks like:
public class GalleryController : Controller
{
// GET: Gallery
public ActionResult Display()
{
return View("Index");
}
public ActionResult Admin()
{
return View();
}
public ActionResult Gifs()
{
if(Request.Url.AbsoluteUri.Contains("gifs/slide"))
return View("GifsSlide");
else
return View("GifsGrid");
}
public ActionResult Still()
{
if (Request.Url.AbsoluteUri.Contains("stil/slide"))
return View("StillSlide");
else
return View("StillGrid");
}
}
Inside my Gallery folder in Views I have following .cshtml structure
Views/Gallrey/gifsgrid.cshtml
Views/Gallrey/gifsslide.cshtml
Views/Gallrey/stillgrid.cshtml
Views/Gallrey/stillslide.cshtml
Views/Gallrey/admin.cshtml
Achievement:
localhost/gallery1/still/grid
localhost/gallery1/still/slide
localhost/gallery1/gifs/grid
localhost/gallery1/gifs/slide
localhost/gallery1/admin
I am trying to pass a folder path to a download controller using #Html.ActionLink, but I am getting could not find the location error like
Could not find file 'C:\Teerth
Content\Project\Colege\WebApp\Media\#item.Content'
However when I give the hard coded value it does work. May I have suggestions what is wrong with that.
Here is my code:
Action method:
public FileResult Download(string fileName, string filePath)
{
byte[] fileBytes = System.IO.File.ReadAllBytes(filePath);
string documentName = fileName;
return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, documentName);
}
view
#Html.ActionLink("Download", "Download", "Marketing", routeValues: new
{
fileName = #item.Content,
filePath = Server.MapPath("~/Media/#item.Content"),
area = "AffiliateAdmin"
}, htmlAttributes: null)
Like mentioned in comments, you've got an error in your view:
The code ("~/Media/#item.Content") renders as C:\Teerth Content\Project\Colege\WebApp\Media\#item.Content, where you actually want Server.MapPath("~/Media/" + #item.Content) to find the actual filename.
But you need to reconsider this design, as it opens up your entire machine to the web. Someone is bound to try Download("C:\Teerth Content\Project\Colege\WebApp\web.config", "web.config"), exposing your connection strings and other application settings, not to mention other files on your server you really don't want clients to download.