Read image from database and display in view

与世无争的帅哥 提交于 2019-12-23 01:37:08

问题


I'm trying to convert an older ASP.NET application to MVC (I am just learning MVC). and I have a need to display an image in a Gridview. The image itself is stored in a SQL Server table as datatype image. The code that was used previously is below. Can someone suggest an approach using MVC? I was thinking of creating a partial page that I could embed in a standard view, but not sure if that is the right design to implement.

Thanks is advance!

   `  string sqlText = "SELECT * FROM Images WHERE img_pk = " + id;
        SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString);

        SqlCommand command = new SqlCommand(sqlText, connection);
        connection.Open();
        SqlDataReader dr = command.ExecuteReader();
        if (dr.Read())
        {
            //Response.Write("test");
           Response.BinaryWrite((byte[])dr["img_data"]);
        }
        connection.Close();
    }

Then it can be referenced using this image tag:

<asp:Image Height="73" Width="80" ID="Image1" ImageAlign="Middle" ImageUrl='<%#"viewimage.aspx?id=" + Eval("ImageId") %>' runat="server"/></a></td>

回答1:


The first thing is to forget about GridView in an ASP.NET MVC application. Server side controls, postbacks, viewstate, events, ... all those are notions that no longer exists.

In ASP.NET MVC you work with Models, Controllers and Views.

So you could write a controller action which will fetch the image from the database and serve it:

public class ImagesController: Controller
{
    public ActionResult Index(int id)
    {
        string sqlText = "SELECT img_data FROM Images WHERE img_pk = @id";
        using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString))
        using (var command = conn.CreateCommand())
        {
            conn.Open();
            command.CommandText = sqlText;
            command.Parameters.AddWithValue("@id", id);
            using (var reader = command.ExecuteReader())
            {
                if (!reader.Read())
                {
                    return HttpNotFound();
                }

                var data = GetBytes(reader, reader.GetOrdinal("img_data"));
                return File(data, "image/jpg");
            }
        }
    }

    private byte[] GetBytes(IDataReader reader, int columnIndex)
    {
        const int CHUNK_SIZE = 2 * 1024;
        byte[] buffer = new byte[CHUNK_SIZE];
        long bytesRead;
        long fieldOffset = 0;
        using (var stream = new MemoryStream())
        {
            while ((bytesRead = reader.GetBytes(columnIndex, fieldOffset, buffer, 0, buffer.Length)) > 0)
            {
                byte[] actualRead = new byte[bytesRead];
                Buffer.BlockCopy(buffer, 0, actualRead, 0, (int)bytesRead);
                stream.Write(actualRead, 0, actualRead.Length);
                fieldOffset += bytesRead;
            }
            return stream.ToArray();
        }
    }
}

and then in your view simply:

<img src="@Url.Action("Index", "Images", new { id = "123" })" alt="" />

Now of course all this controller action is nice and dandy, but you should really abstract all data access into a repository:

public interface IImagesRepository
{
    byte[] GetImageData(int id);
}

then implement this method for the data provider you are using:

public class ImagesRepositorySql: IImagesRepository
{
    public byte[] GetImageData(int id)
    {
        // you already know what to do here.
        throw new NotImplementedException();
    }
}

Finally you will have your controller become database agnostic. Layers in your application are now weakly coupled between them which would allow you to reuse and unit test them in isolation:

public class ImagesController: Controller
{
    private readonly IImagesRepository _repository; 
    public ImagesController(IImagesRepository repository)
    {
        _repository = repository;
    }

    public ActionResult Index(int id)
    {
        var data = _repository.GetImageData(id);
        return File(data, "image/jpg");
    }
}

and the last part would be to configure your favorite DI framework to inject the proper implementation of the repository into the controller.



来源:https://stackoverflow.com/questions/7812534/read-image-from-database-and-display-in-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!