Convert a path (which is an image) to HttpPostedFileBase - asp.net-mvc

I provide for the User to upload an image.
But if it is not done, I want to set a default image in an images folder.
How do I set the model property of type 'HttpPostedFileBase' to the image that is located at the path that I set programmatically?
The model property:
public HttpPostedFileBase UploadedImage { get; set; }
I have tries these with no success.
This one I get: Cannot convert type 'string' to 'System.Web.HttpPostedFileBase'.
if (userProfileForSaveVM.UserProfileSingleVM.UploadedImage == null)
{
// Set a default.
userProfileForSaveVM.UserProfileSingleVM.UploadedImage =
"F:\\GbngWebClient\\GbngWebClient\\Images\\Avatar.png";
}
This one I get: property or indexer 'HttpPostedFileBaseInputStream' cannot be assigned to -- it is read only.
if (userProfileForSaveVM.UserProfileSingleVM.UploadedImage == null)
{
// Set a default.
String pathImage = Server.MapPath("F:\\GbngWebClient\\GbngWebClient\\Images\\Avatar.png");
userProfileForSaveVM.UserProfileSingleVM.UploadedImage.InputStream = new FileStream(pathImage, FileMode.Open);
}
This one I get: Cannot convert type 'byte[]' to 'System.Web.HttpPostedFileBase'.
if (userProfileForSaveVM.UserProfileSingleVM.UploadedImage == null)
{
// Set a default.
byte[] imageArray =
System.IO.File.ReadAllBytes(#F:\\GbngWebClient\\GbngWebClient\\Images\\Avatar.png");
userProfileForSaveVM.UserProfileSingleVM.UploadedImage = imageArray;
}

I am not sure why you would want to create a class of this type. The class is for receiving file data from a HTTP Request. Usually you get data from this class using its input stream. The msdn docs have an example here:
https://learn.microsoft.com/en-us/dotnet/api/system.web.httppostedfile.inputstream?view=netframework-4.8#System_Web_HttpPostedFile_InputStream
What you want to do is get the File Stream from the HttpPostedFileClass, and if there is none, get that file stream from your default location. You can declare an empty memory stream to start with and fill that stream from either the HttpPostedFile or your local resource where appropriate.

try use check null in View like:
if (userProfileForSaveVM.UserProfileSingleVM.UploadedImage != null)
{
<img src= "#Url.Content("~/uploads/FileUpload12011_03_02_11_49_22.jpg")" alt="IMAGES" />
}

Related

MVC Access Resource image

I want to access and return a resource image from a DLL /connected project.
(Its a file, with build action of Resource). It is not listed in properties/resource as there are hundreds of them in the folder.
The idea is that I can call an image controller.
public ImageResult Display(string resourcePath){
Uri uri = new Uri("pack://application:,,,/ProjectName;component/Images/Vectors/" + resourcePath, UriKind.Absolute);
// What goes here??
}
The problem is i dont know how to turn the URI into an image, in MVC5.
I want to be able to call it from the view. using the url property of the <img> tag
I think you could try WebClient.DownloadData() method to download the image as byte array from specified URI, then convert it to Base64 format with Convert.ToBase64String() and display it on <img> tag using a string property in the viewmodel as src attribute value, below is an example to display the image:
Viewmodel Example
public class ViewModel
{
// other properties
// used to pass image into src attribute of img tag
public string ImageData { get; set; }
}
Controller Action
public ActionResult Display(string resourcePath)
{
Uri uri = new Uri("pack://application:,,,/ProjectName;component/Images/Vectors/" + resourcePath, UriKind.Absolute);
using (var wc = new System.Net.WebClient())
{
// download URI resource as byte array
byte[] image = wc.DownloadData(uri);
// get image extension
string path = string.Format("{0}{1}{2}{3}", uri.Scheme, Uri.SchemeDelimiter, uri.Authority, uri.AbsolutePath);
string extension = System.IO.Path.GetExtension(path).Replace(".", "");
// assign image to viewmodel property as Base64 string format
var model = new ViewModel();
model.ImageData = string.Format("data:image/{0};base64,{1}", extension, Convert.ToBase64String(image));
return View(model);
}
}
View
#model ViewModel
<img src="#Model.ImageData" ... />
Additional note:
If you already know the extension from the resource URI, you could use it directly instead of using Path.GetExtension, here is an example for JPG format:
model.ImageData = string.Format("data:image/jpg;base64,{0}", Convert.ToBase64String(image));
Related issues:
Image to byte array from a url
MVC How to display a byte array image from model
Be sure to register the pack:// scheme as this won't automatically be registered in an MVC app as it is in a WPF app.
In this example code, Blarn0 is a public property in my model class to ensure that the access to the PackUriHelper.UriSchemePack property isn't optimized away when the code is published in Release configuration. I'm sure one can use discards for this very purpose in later versions of C#.
const string scheme = "pack";
if (!UriParser.IsKnownScheme(scheme))
Blarn0 = PackUriHelper.UriSchemePack;

Convert HttpPostBasicFile to Image in MVC

I get a picture by uploading and I want to convert it to image file without save it.
how can I do it?
public HttpPostedFileBase BasicPicture { get; set; }
var fileName = Path.GetFileName(BasicPicture.FileName);
// store the file inside ~/App_Data/uploads folder
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
BasicPicture.SaveAs(path);
By this code I can save the picture on the server but I want convert it to image
like
Image img=(Image) BasicPicture;
but it doesn't work.
You could use the FromStream method:
using (Image img = Image.FromStream(BasicPicture.InputStream))
{
... do something with the image here
}
You can also convert HttpPostedFileBase to WebImage (which gives you more API - like method Resize):
public ActionResult SaveUploadedImage(HttpPostedFileBase file)
{
if(file != null)
{
var image = new System.Web.Helpers.WebImage(file.InputStream);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), file.FileName);
image.Save(path);
}
return View();
}
With out knowing exactly what you are doing and why i can give a full intelligent answer.
Personally i would use something like this to open an image. You have saved the image to your server, so instead of casting why not new up a new image? the end result is the same!
WebImage webImage = new WebImage(path);

ASP.NET MVC 3 Preview Image

I'm using MVC 3 and using the AjaxUpload plugin to upload an image using AJAX. I don't want to save the image in the file system, instead save it to the session object and then output the stream to populate an image control on the form? Would anyone know how to do this?
No idea why would ever want to do that (store the file in session) because if you have lots of users uploading their files at the same time, storing those files in the memory of your web server, especially if those files are big, won't make this server last very long. Storing the file on the filesystem is the recommended approach.
But anyway, here's how you could do it (assuming you didn't read or cared about my previous remark):
[HttpPost]
public ActionResult Upload(MyViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var buffer = new byte[model.File.InputStream];
model.File.InputStream.Read(buffer, 0, buffer.Length);
Session["uploadedFile"] = buffer;
return View(model);
}
where the File property on the view models is a HttpPostedFileBase. Next you could have a controller action which will serve this file:
public ActionResult Image()
{
byte[] buffer = (byte[])Session["uploadedFile"];
return File(buffer, "image/png");
}
and in the view you will have an <img> tag pointing to this action:
<img src="#Url.Action("image")" alt="" />
Now of course the AjaxUpload plugin allows you to upload the file using AJAX, so you don't need to reload the entire page. So in this case your controller action could simply return a JSON object to indicate whether the upload process succeeded and then in the success callback set the src property of the <img> tag to the controller action that will serve the file.
SomeView.cshtml:
<img src="#Url.Action("/Image/Render")" />
ImageController.cs:
public ActionResult Render() {
return File((byte[])Session["Avatar"], "image/jpeg")
}
Some example code. Modify it to whatever you want to do. Not really a good idea to sling an image into a session if lots of users. Better to stick it into a db if short lived, or if long lived, a more permanent storage (filesystem maybe).
public ActionResult UploadImage()
{
foreach (string imageName in Request.Files)
{
HttpPostedFileBase file = Request.Files[imageName];
if (file.ContentLength > 0)
{
BinaryReader br = new BinaryReader(file.InputStream);
byte[] content = br.ReadBytes(file.ContentLength);
Session[imageName] = content; // better to store in a db here
}
}
return View();
}
// return the image (controller action) /mycontroller/ViewImage?imageName=whatever
public FileStreamResult ViewImage(string imageName)
{
byte[] content = (byte[])Session[imageName] ; // where ever your content is stored (ideally something other than session)
MemoryStream ms = new MemoryStream(content);
return new FileStreamResult(ms, "application/octet-stream"); // set content type based on input image, it might be png, jpg, gif etc.,
}
Hope this helps.

Difficulties to send File to view using FileContentResult action method

I need to display in image on the view this way
<img src = <% = Url.Action("GetImage", "Home", new { productID })%>
This is the action which's supposed to supply data
public FileContentResult GetImage(int ID)
{
var img = db.Images.Where(p => p.ID == ID).First();
return File(img.ImageData, img.ImageMimeType);
}
This example comes from Pro ASPNET.NET MVC (Steven Sanderson/APress). I'm getting the following error: The best overload method match for System.Web.Mvc.Controller.File(string, string) has some invalid argument. Cannot convert from System.Data.Linq.Binary to string.
Yet, the intellisense's telling me that there's an overload method (byte[] filecontents, string fileType).But, when I write the above code, I get the error. Am I missing something?
EDIT
Thanks for the answer. I've experienced a similar problem while uploading the image file. Here's my action method
public ActionResult AddImage(HttpPostedFileBase image)
{
if(image != null)
{
var img = new Image();//This Image class has been
//created by the DataContext
img.ImageMimeType = image.ImageMimeType
img.ImageData = new byte[image.ContentLength];
image.InputStream.Read(img.ImageData, 0, image.ContentLength);
}
}
I get error for the last line "image.InputStream.Read(myImage.ImageData, 0, image.ContentLength);" It's saying that it can't convert System.Data.Linq.Binary to Byte[]
What I did was (i) to create a new class, called ImageDataClass, (ii) do the above operation against that class, (iii) do the explicit conversion from ImageDataClass to Image, and (iv) save to the DB using Linq.
I don't think it should be that complicate. Is there any way to make it work using simply an extension method such as ToArray as for the other case???
Thanks for helping
There is an overload for File() that takes a byte array, but you are trying to pass in a type of System.Data.Linq.Binary, not a byte array. However, there is a method on Binary to convert to a byte array.
Try this:
public FileContentResult GetImage(int ID)
{
var img = db.Images.Where(p => p.ID == ID).First();
return File(img.ImageData.ToArray(), img.ImageMimeType);
}
The reason the compile error mentions "string" is purely because it can't work out which overload you were trying for, so it just picks one, in this case string, and then reports the type conversion error.
[EDIT: in response to OP edit]
You should be able to try something like this:
public ActionResult AddImage(HttpPostedFileBase image)
{
if(image != null)
{
var img = new Image();//This Image class has been
//created by the DataContext
img.ImageMimeType = image.ImageMimeType
var imageData = new byte[image.ContentLength];
image.InputStream.Read(imageData, 0, image.ContentLength);
img.ImageData = new System.Data.Linq.Binary(imageData);
}
}
Remember that although System.Data.Linq.Binary is probably just a byte array underneath, or is at least intended to represent byte data, it is not itself of type byte[]; you still have to convert to and from (a similar situation to System.IO.MemoryStream)

ASP.NET MVC Dynamically generated image URLs

I have an ASP.NET MVC application where I am displaying images.
These images could be located on the file system or inside a database. This is fine as I can use Url.Action in my image, call the action on my controller and return the image from the relevant location.
However, I want to be able to support images stored in Amazon S3. In this case, I don't want my controller action to return the image, it should instead generate an image URL for Amazon S3.
Although I could just perform this logic inside my view e.g.
<%if (Model.Images[0].ImageLocation == ImageLocation.AmazonS3) {%>
// render amazon image
I need to ensure that the image exists first.
Essentially I need to pass a size value to my controller so that I can check that the image exists in that size (whether it be in the database, file system or amazon s3). Once I am sure that the image exists, then I return the URL to it.
Hope that makes sense,
Ben
Try the following approach.
A model class for an image tag.
public class ImageModel
{
public String Source { get; set; }
public String Title { get; set; }
}
Helper
public static String Image(this HtmlHelper helper, String source, String title)
{
var builder = new TagBuilder("img");
builder.MergeAttribute("src", source);
builder.MergeAttribute("title", title);
return builder.ToString();
}
View with Model.Images of type IEnumerable<ImageModel>
...
<%= Html.Image(Model.Images[0].Source, Model.Images[0].Title) %>
Action
public ActionResult ActionName(/*whatever*/)
{
// ...
var model = ...;
//...
var model0 = ImageModel();
if (Image0.ImageLocation == ImageLocation.AmazonS3)
model0.Source = "an amazon url";
else
model0.Source = Url.Action("GetImageFromDatabaseOrFileSystem", "MyController", new { Id = Image0.Id });
model0.Title = "some title";
model.Images.Add(model0);
// ...
return View(model);
}
An action is a kind of a pseudo code, however the idea should be clear.
After several iterations I have come up with a workable solution, although I'm still not convinced its the best solution.
Originally I followed Anton's suggestion and just set the image url accordingly within my controller action. This was simple enough with the following code:
products.ForEach(p =>
{
p.Images[0].Url = _mediaService.GetImageUrl(p.Images[0], 200);
});
However, I soon found that this approach did not give me the flexibility I needed. Often I will need to display images of different sizes and I don't want to use properties of my model for this such as Product.FullSizeImageUrl, Product.ThumbnailImageUrl.
As far as "Product" is concerned it only knows about the images that were originally uploaded. It doesn't need to know about how we manipulate and display them, or whether we are caching them in Amazon S3.
In web forms I might use a user control to display product details and then use a repeater control to display images, setting the image urls programatically in code behind.
I found that the use of RenderAction in ASP.NET MVC gave me similar flexibility:
Controller Action:
[ChildActionOnly]
public ActionResult CatalogImage(CatalogImage image, int targetSize)
{
image.Url = _mediaService.GetImageUrl(image, targetSize);
return PartialView(image);
}
Media Service:
public MediaCacheLocation CacheLocation { get; set; }
public string GetImageUrl(CatalogImage image, int targetSize)
{
string imageUrl;
// check image exists
// if not exist, load original image from store (fs or db)
// resize and cache to relevant cache location
switch (this.CacheLocation) {
case MediaCacheLocation.FileSystem:
imageUrl = GetFileSystemImageUrl(image, targetSize);
break;
case MediaCacheLocation.AmazonS3:
imageUrl = GetAmazonS3ImageUrl(image, targetSize);
break;
default:
imageUrl = GetDefaultImageUrl();
break;
}
return imageUrl;
}
Html helper:
public static void RenderCatalogImage(this HtmlHelper helper, CatalogImage src, int size) {
helper.RenderAction("CatalogImage", "Catalog", new { image = src, targetSize = size });
}
Usage:
<%Html.RenderCatalogImage(Model.Images[0], 200); %>
This now gives me the flexibility I require and will support both caching the resized images to disk or saving to Amazon S3.
Could do with some url utility methods to ensure that the generated image URL supports SSL / virtual folders - I am currently using VirtualPathUtility.
Thanks
Ben
You can create a HttpWebRequest to load the image. Check the header in the response, if it's 200 that means it was successful, otherwise something went wrong.

Resources