Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying database image (bytes[]) in Razor/MVC3?

Tags:

I am returning a dataset from my MS SQL 2008R2 database that contains a datatable that I am already getting data from on my Razor view. I added a byte[] field that contains an image thumbnail that I am trying to display on that view.

Since the byte array is relatively tiny, I figured I would try displaying the byte array inline. However, after reading there may be some browser-related issues, I abandoned this.

Creating a controller method seemed the way to go, (both methods found here), however I already have the byte array ready to go on my view, and don't need to make another db call to get it based on an ID.

Doing this, doesn't work for obvious reasons:

... displaying other data on the page ....

@if (Model.dsResults.Tables[0].Rows[i]["ImageBytes"] == null) {     <img src="@Url.Content("~/Content/Images/NoPhoto.png")" border="0" /> } else {     <img src="@Url.Action("GetImage", "SearchResults", new { imageBytes = Model.dsResults.Tables[0].Rows[i]["ImageBytes"] })" alt="Product Image" /> } 

...

Controller method:

[Authorize] [AcceptVerbs(HttpVerbs.Get)] public ActionResult GetImage(byte[] imageBytes) {     byte[] byteArray = imageBytes;     return new FileContentResult(byteArray, "image/jpeg"); } 

... as this essentially is attempting to send the byte array over http.

So, my question is, since I already have the byte array on my Razor view, how do I display it?

-- Update --

I realize that doing processing in the view isn't recommended, but since the data is already there, can't something like this be done:

Response.Write((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]); 

Or...

Stream s = new MemoryStream(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"])); System.Drawing.Image img = new System.Drawing.Bitmap(s); 

In other postings I've read that you an do a Response.Write(byte[]...)) but this doesn't work in this case.

-- UPADATE --

In my ongoing search for efficiency (not having to make another request to the db) the WebImage helper seems to be a good candidate. One of its constructors will accept a byte array to initialize the class, then using the .Write("jpeg") method, I can see the image.

<td>     @{         WebImage webImage = new WebImage(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]));         webImage.Write("jpeg");     } </td> 

The problem with using WebImage.Write() is that once used, the image is the only thing that renders on the page. Is there a way to render this directly to a "control" on a Razor view page?

-- UPDATE --

This continues to bug me... so I tried the following, which I figured may work, since this is what we're doing from the Action...

if (Model.dsResults.Tables[0].Rows[i]["ImageBytes"] != DBNull.Value) {     var img1 = new FileContentResult(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]), "image/jpeg");     <text>         <img src="@new FileContentResult(((byte[])Model.dsResults.Tables[0].Rows[i]["ImageBytes"]), "image/jpeg")" />     </text> } 

... doesn't work.

like image 536
ElHaix Avatar asked Dec 12 '11 13:12

ElHaix


2 Answers

Model.Content is a byte[] image.

@{     string imageBase64 = Convert.ToBase64String(Model.Content);     string imageSrc = string.Format("data:image/gif;base64,{0}", imageBase64); } 

Used like so:

<img src="@imageSrc" alt="@Model.Name" width="100" height="100" /> 
like image 199
lbancarz Avatar answered Oct 25 '22 09:10

lbancarz


Eventually, I went for the two trips route. Highly inefficient, as the image bytes were already ready to go on the view. There should be a web helper image control that will render the image directly from the image's byte array (or image type). Maybe there is and I missed it.

To get the bytes (yes, all over again):

    [AcceptVerbs(HttpVerbs.Get)]     public ActionResult GetThumbnailImage(string itemListID)     {         byte[] imageBytes = null;          client = new FeederServiceClient();         imageBytes = client.GetItemThumbnail( itemListID );          if (imageBytes == null)         {             return new FilePathResult("~/Content/Images/NoPhoto.png", "image/png");         }         else         {             return new FileContentResult(imageBytes, "image/jpeg");         }     } 

Then to display the image:

<img src="@Url.Content("~/Thumbnails/" + @Model.dsResults.Tables[0].Rows[i]["ItemListID"] )" /> 

With the following route placed in Global.asax:

routes.MapRoute(name: "Thumbnails", url: "Thumbnails/{itemListID}", defaults: new { controller = "Results", action = "GetThumbnailImage" }); 
like image 29
ElHaix Avatar answered Oct 25 '22 11:10

ElHaix