Display image from IMAGE object in MVC - asp.net-mvc

I have an object of type IMAGE which holds image.
I wanted to display the image in MVC view along with other controls.
The way i can think of is to temporary store image on disk and set src of img control.
I am sure there would be better way of doing this.

The easiest way to do this in my opinion would be to return a FileStreamResult from your controller.
public FileResult GetImage()
{
string path = "c:\images\image.jpg";
return new FileStreamResult(new FileStream(path, FileMode.Open), "image/jpeg");
}
This is a simple implementation, but gives you a starting point for what you are attempting to do.

If you are interested in implementing #Giovanni's answer, then I have some code that may be helpful from a past answer I gave located here. The ImageHandler class is an example of what you would want to implement in Giovanni's case.

You can write a handler to stream images out and then reference the streamer in your image tag.
For instance, you have http://myapp/media.ashx?imageId=10 stream out the image. In your page you reference like so:
<img src="http://myapp/media.ashx?imageId=10"/>.
This way you don't have to temporarily write to disk.

You can serve your image as the response content of a controller action. this response will have the image type as content type.

You can convert the image to Base64 string and assign it to the src attribute of the img tag.
<img alt="Embedded Image" width="168" height="32"
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKgA..." />
http://www.greywyvern.com/code/php/binary2base64

Related

What sort of Image should I use in my model, when the aim is to display this image in a view?

I am in a situation where I am storing images as byte arrays in a SQL database. I am using EF, and so have a byte array automatic property in my model, which is then committed to the database via code first.
I want to put a read only property which is an Image into my model, and convert the byte array to an Image when the get accessor is called. Two questions:
What sort of Image should I use? Should it be a System.Drawing image, or a newer BitmapImage?
Will this cause any problems in regards to code-first and EF?
I can post code if you wish, but I didn't think it was necessary, if anybody wants to see my code, just leave a comment.
1) What sort of Image should I use? Should it be a System.Drawing
image, or a newer BitmapImage?
None of them. You should use a byte array (byte[]).
2) Will this cause any problems in regards to code-first and EF?
I don't think so. I am not an expert with EF but I think it should be possible to map a byte[] property to the corresponding varbinary(max) column in your database.
Now back to your original question about showing an image and having a property on your view model. Even if you do that you cannot display this byte array property as an image inside your view unless you use the data uri scheme which is not widely supported by all browsers. Here's how this might look like if you decide to go that route:
#model MyViewModel
...
<img src="data:image/png;base64,#Html.Raw(Convert.ToBase64String(Model.Image))" alt="some image">
But if you are looking for a solution that will work across all browsers as an alternative you could design a controller action that will fetch your image from the database as a byte array and then stream it to the response. Next from your view you could reference this action inside an <img> tag.
Let's take an example:
public ActionResult Image(int id)
{
byte[] imageData = ... go query your database to retrieve the corresponding
image record using the id
return File(imageData, "image/png");
}
and then inside your main view simply point an <img> tag to this controller action:
#model MyViewModel
...
<img src="#Url.Action("Image", "SomeController", new { id = Model.Id })">

What is the best practice to render an image in MVC from one call to get an aggregate

I have an issue that I would like some opinions on. I totally understand that I CANNOT render an image (byte[]) directly from my viewmodel. I understand that I need to have an id that represents my image in my view model.
Once I bind my viewmodel to my view I can then do something like the following:
<img src="#Url.Action("GetPhoto", new { photoId = Model.PhotoId })" />
And then this:
public ActionResult GetPhoto(int photoId)
{
byte[] photo = GetPhotoFromDb(photoId);
return File(photo, "image/jpeg");
}
However, I have a call to a 3rd party web service (I do not control this) that I call to get an aggregate that populated my viewmodel. Some thing like this:
-Vehicle
-VehicleId
-VehicleName
-VehicleImage byte[] <=======
-VehicleServiceHistory
-ServiceHistoryId
-SericeType
-ServiceTitle
So in theory I could call up the 3rd party web service people and say, I know you are already giving my the VehicleImage in the aggregate (above) but can I please have a separate call to a new service method called GetImageById(int imageId).
So lets assume they say no. So all I have is an aggregate of data that already has my image but I know I have to load the image to the view separately like I stated above:
<img src="#Url.Action("GetPhoto", new { photoId = Model.PhotoId })" />
I could do something nasty like add the image to session when the aggregate comes down from the web service and interrogate session to get the image back with the photoId but there is no way I want to do this.
Can anyone give me any ideas on how I can utilize the, already available, image in the aggregate without having to do another call.
Note: I am totally ok with calling a separate action:
public ActionResult GetPhoto(int photoId)
{
byte[] photo = GetPhotoFromDb(photoId);
return File(photo, "image/jpeg");
}
But I want to use the image that was already supplied in the aggregate in this action and not have to call the service again.
Looking forward to hearing your suggestions.
thanks
RuSs
Note: This post has been up here for a couple of weeks, surely someone has an opinion!! :(
I totally understand that I CANNOT render an image (byte[]) directly from my viewmodel
Well actually you can if the browser supports the data URI scheme:
<img src="data:image/jpeg;base64,#Html.Raw(Convert.ToBase64String(Model.VehicleImage))" />
Other than that there are not much choices left. You will have to persist the image somewhere on the server between the 2 HTTP calls. I congratulate you for the fact that you do not wish to use the Session for that. It's not the right storage for that. One possibility would be to persist the image on some folder on your server (shared folder if you are running on a webfarm) and then only reference the image by id. So basically you will be caching the remote images on your infrastructure. You could have some scheduled scripts that are deleting files older than some date that you could define.
The answer to this is that you have to populate the view model that would contain an id of the image you want to render.
Once the viewmodel has rendered you must call another controller action like this:
public ActionResult GetPhoto(int photoId()
{
byte[] photo = GetPhotoFromDb(photoId);
return File(photo, "image/jpeg");
}
After much investigation it seem this is just the way it is unless all browsers support data URI scheme.
<img src="data:image/jpeg;base64,#Html.Raw(Convert.ToBase64String(Model.VehicleImage))" />
Hope this helps.

How do I code PDF download from external site on Image click?

I have one "Download PDF" Image link, I am calling an action of a controller in order to allow users to download specific file from external site (so has given complete URL of PDF file link)
I have written following code, but its not working.
public virtual ActionLink OpenPDF()
{
string fileName = "http://mysite/filetodownload.pdf";
return File(fileName, "application/pdf", Server.UrlEncode(fileName);
}
This controller action gets called from an Image link.. and I can see this action gets called..
When I click on image, the code gets executed, and asks to Open/Save file, but when I say Save it says "This file cannot be downloaded"
what do you think can be wrong here.
Why don't you just point your link directly to the site
Download File
You don't need to go through a controller for this
As a side not, if you are returning a FileResult you need to pass it a stream, a byte array, or a path to a file on disk. You can't pass it a third party URL. It doesn't work like that. It is meant to work like this:
public virtual ActionLink OpenPDF()
{
string fileName = Server.MapPath("~/Download/filetodownload.pdf");
return File(fileName, "application/pdf");
}
I think
Show images in table from database in Asp.net-mvc3
Azure blobs and thumbnails
ASP.NET MVC - user managment of folder with pictures (FTP?)
links as you meet the answer.

How do you get the full URL of a file uploaded using an Upload object in Java Play?

I'm writing an image uploader in Java Play! in the style of
https://gist.github.com/1256286#file-picture-java-L3
This is great. The image is rendered using this function in the Controller object (here, Picture is a Model implementation that has metadata about an image file:
public static void show(Long id) {
Logger.info("loading id=%s", id);
Picture picture = Picture.findByKey(id);
response.setContentTypeIfNotSet(picture.contentType);
renderBinary(new ByteArrayInputStream(picture.file), picture.file.length);
}
I want to add a url member to Picture that contains the absolute URL to this function for a given picture. How can I populate this member in a way that works irrespective of where the Java Play! application is hosted?
Although I didn't try it in version 1.x I suggest to check the Router API, there are some methods which indicates, that they can optionally create an absolute route (I'm Play 2 user and have no experience with them).
There are also methods like ie. getBaseUrl() or getFullUrl(String action, Map<String,Object> args) so I just guess that they probably will help you to resolve the problem.

ASP.net MVC - Display series of images based on byte[]

I want to display a list of images and a description on a webpage using ASP.net MVC. The images are stored in a SQL Server DB and i'm getting them back as a byte[].
However, I don't understand how I can display a series of images on a page. I want to do something like this:
<% foreach(Product p in Model.Products)
Response.Write(p.Description)
Response.Write(html.Image(p.ImageArray)
%>
But the only code I've saw has been displaying a single image...
Thank you
Ben
Rather than creating a new HttpHandler you can just write a controller action that returns the contents of the image file. Then add images to the page with their src attribute set to the action you created.
EDIT: Note that streaming images as byte[] from a database is inefficient compared to serving static files.
You will need to create a custom IHttpHandler that will serve the images something like this:
public class AlbumArt : IHttpHandler
{
public void ProcessRequest(HttpContext Context)
{
byte [] b = your image...;
Context.Response.ContentType = "image/jpeg";
Context.Response.BinaryWrite(b);
}
}
And then you would need to retrieve each image from there by using image tags in your html, something like
<img src="AlbumArt.ashx?imageId=1" />
Images in HTML are external links, not embedded in the HTML itself. So you do need two requests. However you can optimize this a bit. In the first request, don't retrieve the image data itself, just the meta-data. Then in your HttpHandler, actually retrieve the binary image data.
Each image will have to be sent separately (which means creating an IMG request from the browser for each) or you will have to join them into a single image before sending back. If you run the code above it is likely you will see the first image only.

Resources