Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Good way to retrieve images stored as bytes array in the db using ASP.NET MVC4?

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

like image 879
Nmktronas Avatar asked Aug 09 '13 20:08

Nmktronas


People also ask

How can I get image from byte array?

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).


3 Answers

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

  1. The connection to EF
  2. the call to locate the image
  3. something for the image name
  4. possibly change the output cache
like image 63
Richard Harrison Avatar answered Nov 02 '22 23:11

Richard Harrison


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" />
like image 34
Timothy Shields Avatar answered Nov 02 '22 23:11

Timothy Shields


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"

like image 2
Saman Qaydi Avatar answered Nov 02 '22 22:11

Saman Qaydi