从数据库中读取图像并在视图中显示
问题描述:
我试图将旧的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>
答
的第一件事就是约在GridView的ASP.NET MVC应用程序忘记。服务器端控件,回发,视图状态,事件......所有这些都是不再存在的概念。
在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框架注入库的正确实施进入控制器。
代码是动作方法,Image控件是图片标签,ImageUrl是图片标签的动作url。有点。 – bzlm