从数据库中读取图像并显示在视图中

发布于 2024-12-10 09:03:36 字数 946 浏览 0 评论 0原文

我正在尝试将旧的 ASP.NET 应用程序转换为 MVC(我刚刚学习 MVC)。我需要在 Gridview 中显示图像。图像本身作为数据类型图像存储在 SQL Server 表中。之前使用的代码如下。有人可以建议一种使用 MVC 的方法吗?我正在考虑创建一个可以嵌入标准视图的部分页面,但不确定这是否是正确的实现设计。

感谢是提前!

   `  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();
    }

然后可以使用这个图像标签来引用它:

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

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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

满地尘埃落定 2024-12-17 09:03:36

第一件事是忘记 ASP.NET MVC 应用程序中的 GridView。服务器端控制、回发、视图状态、事件……所有这些概念都不再存在。

在 ASP.NET MVC 中,您使用模型、控制器和视图。

因此,您可以编写一个控制器操作,该操作将从数据库中获取图像并为其提供服务:

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();
        }
    }
}

然后在您的视图中简单地说:

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

当然,所有这些控制器操作都很好,但您应该真正将所有数据访问抽象到存储库中:

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

然后为您正在使用的数据提供者实现此方法:

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

最后您将使您的控制器变得与数据库无关。应用程序中的层现在在它们之间弱耦合,这将允许您单独重用和单元测试它们:

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");
    }
}

最后一部分是配置您最喜欢的 DI 框架以将存储库的正确实现注入到控制器中。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文