I'm programming an ASP.NET MVC4 application which stores uploaded images as byte[]
in a database (with Entity framework) and then displays them. To display the images I'm using this code in the view:
<img src="data:image;base64,@System.Convert.ToBase64String(item.ImageByte)" alt=""/>
But each time I refresh the page I see that the browser does not cache the image and just renders it again causing unecessary bandwith usage.
Maybe there's a more bandwith friendlier way to display the image? Maybe the idea to store uploaded image as 'byte[]' was stupid in the first place (my application is just a simple web page which stores articles about psychology :D with an admin panel to achieve this) and I should just store images in a folder?
Thanks
To convert a byte array to an image. Create a ByteArrayInputStream object by passing the byte array (that is to be converted) to its constructor. Read the image using the read() method of the ImageIO class (by passing the ByteArrayInputStream objects to it as a parameter).
Storing the image in the database is one possible option. There are times when it is a good idea, and times when a bad idea. Generally if dealing with large amounts or large sized images you may be advised to reconsider using a different storage method.
Effectively what you're currently doing is embedding the image in the HTML; this can be good I've used it before when it would take around 5 seconds to calculate the data for a graph and the same data is required for the page, but in general usage you'd be better off serving the image from an action.
So what we need to do is to provide an action in a controller to get the image; probably based on id - but that I'll leave up to you.
[OutputCache(Duration = 3600, VaryByParam = "id")]
public ActionResult GetImage(int Id)
{
// 1. provide connection to entity framework
var dbc = new DatabaseContext();
var item = dbc.FindItem(Id);// call to get the image from EF (2)
var ms = new MemoryStream(tem.ImageByte);
FileStreamResult result = new FileStreamResult(ms, "image/png");
result.FileDownloadName = item.ImageName; // or item.Id or something (3)
return result;
}
in the cshtml
<img src="@Url.Action("GetImage", "Controller", new {Id = Model.ImageId})" />
So in the above code you need to provide
In your HomeController
add a function like this:
[HttpGet]
public FileResult GetImage(string id)
{
byte[] fileContents = ...; // load from database or file system
string contentType = "image/jpeg";
return File(fileContents, contentType);
}
Register a route to this handler in Global.asax.cs
:
routes.MapRoute(
"GetImage",
"img/{id}",
new { controller = "Home", action = "GetImage" });
In your webpage, use a src
pointing to this action:
<img src="@Url.Action("GetImage", "Home", new { id = "logo.jpg" })" />
which will resolve to
<img src="/img/logo.jpg" />
add Generic Handler
public class Handler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
long id = Convert.ToInt64(System.Web.HttpContext.Current.Request.QueryString["id"]);
string model = (System.Web.HttpContext.Current.Request.QueryString["model"]);
DbContext Db = new DbContext();
byte[] picture = new byte[0];
switch (model)
{
case "News":
NameSpace.Models.News news = Db.Newss.Single<NameSpace.Models.News>(n => n.ID == id);
picture = news.Picture;
break;
case "Article":
NameSpace.Models.Article article = Db.Articles.Single<NameSpace.Models.Article>(a => a.ID == id);
picture = article.Picture;
break;
}
context.Response.Clear();
context.Response.ContentType = "image/jpeg";
context.Response.BinaryWrite(picture);
context.Response.Flush();
context.Response.End();
}
public bool IsReusable
{
get
{
return false;
}
}
}
*and in view use this sorce for image img src="/Handlers/[email protected]&model=News"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With