我想要实现的就是这个。我想让用户能够上传图像文件,将图像存储在 SQL Server 的 BLOB 中,然后将此图像用作站点其他页面中的徽标。
我通过使用
做到了这一点
1 2 3 4
| Response.Clear();
Response.ContentType ="image/pjpeg";
Response.BinaryWrite(imageConents);
Response.End(); |
但要做到这一点,我在要显示图像的地方使用了一个用户控件。如果可能的话,我想使用 asp:Image 控件,甚至是纯旧的 html 图像控件。这可能吗?
将\\'Generic Handler\\' 添加到您的Web 项目中,将其命名为Image.ashx 之类的名称。像这样实现它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class ImageHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
using(Image image = GetImage(context.Request.QueryString["ID"]))
{
context.Response.ContentType ="image/jpeg";
image.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
}
public bool IsReusable
{
get
{
return true;
}
}
} |
现在只需实现 GetImage 方法来加载具有给定 ID 的图像,就可以使用
显示它。您可能还想考虑在处理程序中实现某种形式的缓存。请记住,如果要将图像格式更改为 PNG,则需要使用中间 MemoryStream(因为 PNG 需要保存可查找的流)。
您可以将图像的内容直接 BASE64 编码到 SRC 属性中,但是,我相信只有 Firefox 才能将其解析回图像。
我通常做的是创建一个非常轻量级的 HTTPHandler 来提供图像:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| using System;
using System.Web;
namespace Example
{
public class GetImage : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if (context.Request.QueryString("id") != null)
{
Blob = GetBlobFromDataBase(id);
context.Response.Clear();
context.Response.ContentType ="image/pjpeg";
context.Response.BinaryWrite(Blob);
context.Response.End();
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
} |
您可以直接在 img 标签中引用它:
1
| <img src="GetImage.ashx?id=111"/> |
或者,您甚至可以创建一个服务器控件来为您执行此操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Example.WebControl
{
[ToolboxData("<{0}:DatabaseImage runat=server></{0}:DatabaseImage>")]
public class DatabaseImage : Control
{
public int DatabaseId
{
get
{
if (ViewState["DatabaseId" + this.ID] == null)
return 0;
else
return ViewState["DataBaseId"];
}
set
{
ViewState["DatabaseId" + this.ID] = value;
}
}
protected override void RenderContents(HtmlTextWriter output)
{
output.Write("<img src='getImage.ashx?id=" + this.DatabaseId +"'/>");
base.RenderContents(output);
}
}
} |
这可以像
那样使用
1
| <cc:DatabaseImage id="db1" DatabaseId="123" runat="server/> |
当然,您可以根据需要在代码隐藏中设置 databaseId。
您不希望在不实施客户端缓存的情况下从数据库提供 blob。
您将需要处理以下标头以支持客户端缓存:
-
标签
-
过期
-
上一次更改
-
如果匹配
-
如果不匹配
-
If-Modified-Since
-
If-Unmodified-Since
-
除非修改自
对于执行此操作的 http 处理程序,请查看:
http://code.google.com/p/talifun-web/wiki/StaticFileHandler
它有一个很好的帮手来提供内容。将数据库流传递给它应该很容易。它还进行服务器端缓存,这应该有助于减轻数据库的一些压力。
如果您决定从数据库、pdf 或大文件提供流媒体内容,处理程序还支持 206 个部分请求。
它还支持 gzip 和 deflate 压缩。
这些文件类型将受益于进一步压缩:
-
css、js、htm、html、swf、xml、xslt、txt
-
文档、xls、ppt
有些文件类型无法从进一步压缩中受益:
-
pdf(在 IE 中会导致某些版本出现问题,并且通常会被很好地压缩)
-
png、jpg、jpeg、gif、ico
-
wav、mp3、m4a、aac(wav 经常被压缩)
-
3gp、3g2、asf、avi、dv、flv、mov、mp4、mpg、mpeg、wmv
-
zip、rar、7z、arj
在 MVC 中使用 ASP.Net 这非常容易。你用这样的方法编写控制器:
1 2 3 4 5 6 7 8 9 10 11 12
| public FileContentResult Image(int id)
{
//Get data from database. The Image BLOB is return like byte[]
SomeLogic ItemsDB= new SomeLogic("[ImageId]=" + id.ToString());
FileContentResult MyImage = null;
if (ItemsDB.Count > 0)
{
MyImage= new FileContentResult(ItemsDB.Image,"image/jpg");
}
return MyImage;
} |
在您的 ASP.NET Web 视图中或在此示例中,在您的 ASP.NET Web 窗体中,您可以使用指向您的方法的 URL 填充图像控件,如下所示:
1 2 3
| this.imgExample.ImageUrl ="~/Items/Image/" + MyItem.Id.ToString();
this.imgExample.Height = new Unit(120);
this.imgExample.Width = new Unit(120); |
瞧。不需要 HttpModules 麻烦。
将代码添加到处理程序以返回具有适当 mime 类型的图像字节。然后您可以将 url 添加到您的处理程序中,就像它是一个图像一样。例如:
1
| <img src="myhandler.ashx?imageid=5"> |
有意义吗?
我们实际上刚刚发布了一些有助于解决此类问题的类:
http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=16449
具体来说,请查看 DatabaseImage 示例。