使用IHttphandler为图片添加水印和防盗链功能
用IHttphandler实现为图片添加水印是Aspnet中很经典的做法了,这方面的介绍网上很多,不过还是会有一些细节方面的问题值得注意,可能会因为某些细节的处理不好而出不来效果。对于开发而言,理解了、懂了不能算真正掌握,只有写出来,调试通过,部署成功,运行没有问题才算OK。
本文将图片添加水印功能的技术实现、web.config配置、IIS配置等按操作步骤梳理出来,对于可能遇到的问题进行了分析。既方便初学者按部就班的演练,也为有经验的开发者在排查问题时提供参考。另外,顺带加上了防盗链功能,对添加文字水印和Logo水印的情况也相应给出了两种图片处理方案。
下面,就按步骤开始吧!
步骤一:新建一个类WaterMark,实现IHttphandler接口
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Web;
public class WaterMark : IHttpHandler
{
public bool IsReusable
{
get { throw new NotImplementedException(); }
}
public void ProcessRequest(HttpContext context)
{
throw new NotImplementedException();
}
}
检查文件的相关属性,复制到输出目录选择“不复制”,生成操作为“编译”,如下:
步骤二:重写WaterMark类的方法,实现相应的功能
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/jpeg";
//盗链下载(输出防盗链图片)
Uri urlRef = context.Request.UrlReferrer;
Uri url = context.Request.Url;
if (!IsSameDomain(urlRef, url))
{
string daolianPath = context.Request.MapPath("~/Images/daolian.jpg");
context.Response.WriteFile(daolianPath);
}
//正常下载(在图片上添加水印文字)
else
{
//获取提交的图片路径
string path = context.Request.RawUrl;
path = context.Request.MapPath(path);
//画板
using (Bitmap bitmp = new Bitmap(path))
{
//画笔
using (Graphics g = Graphics.FromImage(bitmp))
{
Font font = new System.Drawing.Font("微软雅黑", 14, (System.Drawing.FontStyle.Italic));
System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, bitmp.Width, bitmp.Height), Color.White, Color.White, 1.2f, true);
g.DrawString("iprogram.com.cn", font, brush, bitmp.Width - 165, bitmp.Height - 32);
}
bitmp.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
//UriComponents.HostAndPort,比较两个路径的域名
//UriFormat.SafeUnescaped,具有保留意义的字符仍进行转义
//StringComparison.CurrentCultureIgnoreCase,使用区域敏感排序规则,当前区域比较,忽略大小写
bool IsSameDomain(Uri url1, Uri url2)
{
return Uri.Compare(url1, url2, UriComponents.HostAndPort, UriFormat.SafeUnescaped, StringComparison.CurrentCultureIgnoreCase) == 0;
}
public bool IsReusable
{
//有并发同时存在的情况下,当前的handle调用了某个独占的线程(进程),那么就需要设置为false。比如说,handle独占写入某个文本文件(所有的并发都需要写入这个),那就需要设置为false了。
//如果handle没有这种非安全的情况,就可以直接设置为true。通常大多数项目都设置为true的
get { return false; }
}
步骤三:web.config配置
(1)带程序集名的配置
<system.web>
<httpHandlers>
<add path="Upload/Images////////.jpg" type="WaterMark" verb="*" />
<add path="Upload/Images////////.png" type="WaterMark" verb="*" />
</httpHandlers>
</system.web>
以上配置可能出现以下报错:
配置错误
说明: 在处理向该请求提供服务所需的配置文件时出错。请检查下面的特定错误详细信息并适当地修改配置文件。
分析器错误消息: 类型“WaterMark”不明确: 它可能来自程序集“C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\3f8eda58\df96fc10\App_Code.kgqjr5m3.DLL”或程序集“I:\i编程网\IProgram.CMS\IProgram.CMS.UI.Portal\bin\IProgram.CMS.UI.Portal.DLL”。请在类型名称中显式指定程序集。
(2)带程序集名的配置
如果报错提示有多个程序集包含该类,要求显示指定程序集,可按如下方式进行配置:
<system.web>
<httpHandlers>
<add path="Upload/Images////////.jpg" type="WaterMark,IProgram.CMS.UI.Portal" verb="*" />
<add path="Upload/Images////////.png" type="WaterMark,IProgram.CMS.UI.Portal" verb="*" />
</httpHandlers>
</system.web>
步骤四:IIS配置
经过以上配置,运行VS调试,可看到图片上都打上了“iprogram.com.cn”文字的水印。效果如下图所示:
但是发布到IIS后,运行发现该功能没有生效,图片上并没有出现水印。这是由于,在默认情况下,jpg、png等这些图片资源的属于静态资源,IIS会将资源找到直接响应给客户端,并不经过aspx程序的处理再输出。
我们知道IIS在接到请求后会查询应用程序扩展的映射表,以决定哪些类型的请求交给什么应用程序处理,对于映射表中没有配置的静态资源会直接输出。要将图片请求交给aspnet服务端处理,只要在映射表中为其添加一条记录,关联aspnet_isapi.dll即可。具体配置步骤如下:
(1)找到网站->右键打开属性窗口
(2)主目录->点击“配置”进行设置
(3)映射->添加
点击“浏览”到.netframework 版本号文件夹下找到aspnet_isapi.dll,扩展名写图片的后缀名,如jpg,到此配置完成。(如果有多种后缀名的如png,需要为png添加一条新的映射记录。)
附:为图片添加Logo水印
有时候可能希望给图片打上一个自己公司的Logo做为谁赢,而不是文字水印。可以将图片处理这块代码改成如下的代码:
//获取提交的图片路径
string path = context.Request.RawUrl;
path = context.Request.MapPath(path);
//水印图片的路径
string logoPath = context.Request.MapPath("~Images/logo.png");
//原始图片
using (Image img = Image.FromFile(path))
{
//水印图片
using (Image logoImg = Image.FromFile(logoPath))
{
using (Graphics g = Graphics.FromImage(img))
{
g.DrawImage(logoImg, 0, 0, logoImg.Width, logoImg.Height);
img.Save(context.Response.OutputStream,
System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
(全文完)
(转载本文请注明作者和出处 i 编程网-iprogram.com.cn ,请勿用于任何商业用途)