需求:
1、为所有的大图添加水印
2、不要直接在图片上生成水印,要保持图片的原汁原味
3、要求可配置,配置的选项包括是否启用水印,水印图片可以更换,水印的位置可以更换
解决方案:
在我们的图片管理系统中,用户上传的图片都通过一个二级域名进行管理,如 images.photocms.com
所以就只需在这个应用中,拦截所有的图片请求交由asp.net处理,在asp.net程序中处理原图和水印图片,
将结果输出给用户即可。
具体步骤如下:
1、配置IIS,将jpg后缀名的请求用aspnet_isapi.dll来接收处理。
2、配置Web.config ,添加.jpg处理程序对应的具体asp.net类
<add verb="*" path="*.jpg" type="PhotoCms.Common.WaterMark,PhotoCms.Common" />
具体技术实现:
其中具体的 HttpHandler 程序
public class WaterMark : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
HttpResponse Response = context.Response;
HttpRequest Request = context.Request;
Response.ContentType = " image/jpeg " ;
string filePath = Request.FilePath;
string physicalPath = context.Server.MapPath(filePath);
if ( ! File.Exists(physicalPath))
return ;
string waterImagePath = context.Server.MapPath( " /watermark.png " );
IList < string > ruleList = new List < string > ();
string isOpen = string .Empty;
int padding = 10 ;
watermarkConfig objWaterConfig = watermarkConfig.GetInstance();
if (objWaterConfig != null )
{
isOpen = objWaterConfig.isOpen;
waterImagePath = context.Server.MapPath(objWaterConfig.filePath);
ruleList = objWaterConfig.rules;
padding = objWaterConfig.padding;
}
bool doWaterMark = false ;
foreach ( string _rule in ruleList)
{
if (filePath.Contains(_rule))
{
doWaterMark = true ;
continue ;
}
}
if (isOpen.Equals( " 1 " ) && doWaterMark)
{
physicalPath = context.Server.MapPath(filePath);
ImageHelper obj = new ImageHelper(physicalPath);
obj.InsertImage(waterImagePath, Common.WathermarkPosition.BottomRight,padding);
obj.GetImage().Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
obj.Dispose();
}
else
{
physicalPath = context.Server.MapPath(filePath);
byte [] buffer = new Byte[ 10000 ];
int length;
long dataToRead;
System.IO.Stream iStream = null ;
iStream = new System.IO.FileStream(physicalPath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
dataToRead = iStream.Length;
Response.Buffer = false ;
while (dataToRead > 0 )
{
if (Response.IsClientConnected)
{
length = iStream.Read(buffer, 0 , 10000 );
Response.OutputStream.Write(buffer, 0 , length);
Response.Flush();
buffer = new Byte[ 10000 ];
dataToRead = dataToRead - length;
}
else
{
dataToRead = - 1 ;
}
}
iStream.Close();
}
}
public bool IsReusable
{
get
{
return false ;
}
}
}
public class watermarkConfig
{
public string isOpen = string .Empty;
public string filePath = string .Empty;
public int padding = 0 ;
public IList < string > rules = new List < string > ();
private static watermarkConfig instance;
private watermarkConfig()
{
loadConfigFile();
}
public static watermarkConfig GetInstance()
{
if (instance == null )
{
instance = new watermarkConfig();
}
return instance;
}
private void loadConfigFile()
{
string configFile = HttpContext.Current.Request.ApplicationPath + " /config/photo/photo.config " ;
XmlDocument xml = new XmlDocument();
xml.Load(HttpContext.Current.Server.MapPath(configFile));
XmlNode waterroot = xml.SelectSingleNode( " picture/watermark " );
this .isOpen = waterroot.Attributes[ " isOpen " ].Value;
this .filePath = waterroot.Attributes[ " filePath " ].Value;
this .padding = Convert.ToInt32(waterroot.Attributes[ " padding " ].Value);
foreach (XmlNode rule in waterroot.ChildNodes)
{
if (rule.NodeType != XmlNodeType.Comment)
{
if (rule.Name.ToLower().Equals( " rule " ))
{
rules.Add(rule.Attributes[ " urlfrom " ].Value);
}
}
}
}
}
public void ProcessRequest(HttpContext context)
{
HttpResponse Response = context.Response;
HttpRequest Request = context.Request;
Response.ContentType = " image/jpeg " ;
string filePath = Request.FilePath;
string physicalPath = context.Server.MapPath(filePath);
if ( ! File.Exists(physicalPath))
return ;
string waterImagePath = context.Server.MapPath( " /watermark.png " );
IList < string > ruleList = new List < string > ();
string isOpen = string .Empty;
int padding = 10 ;
watermarkConfig objWaterConfig = watermarkConfig.GetInstance();
if (objWaterConfig != null )
{
isOpen = objWaterConfig.isOpen;
waterImagePath = context.Server.MapPath(objWaterConfig.filePath);
ruleList = objWaterConfig.rules;
padding = objWaterConfig.padding;
}
bool doWaterMark = false ;
foreach ( string _rule in ruleList)
{
if (filePath.Contains(_rule))
{
doWaterMark = true ;
continue ;
}
}
if (isOpen.Equals( " 1 " ) && doWaterMark)
{
physicalPath = context.Server.MapPath(filePath);
ImageHelper obj = new ImageHelper(physicalPath);
obj.InsertImage(waterImagePath, Common.WathermarkPosition.BottomRight,padding);
obj.GetImage().Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
obj.Dispose();
}
else
{
physicalPath = context.Server.MapPath(filePath);
byte [] buffer = new Byte[ 10000 ];
int length;
long dataToRead;
System.IO.Stream iStream = null ;
iStream = new System.IO.FileStream(physicalPath, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
dataToRead = iStream.Length;
Response.Buffer = false ;
while (dataToRead > 0 )
{
if (Response.IsClientConnected)
{
length = iStream.Read(buffer, 0 , 10000 );
Response.OutputStream.Write(buffer, 0 , length);
Response.Flush();
buffer = new Byte[ 10000 ];
dataToRead = dataToRead - length;
}
else
{
dataToRead = - 1 ;
}
}
iStream.Close();
}
}
public bool IsReusable
{
get
{
return false ;
}
}
}
public class watermarkConfig
{
public string isOpen = string .Empty;
public string filePath = string .Empty;
public int padding = 0 ;
public IList < string > rules = new List < string > ();
private static watermarkConfig instance;
private watermarkConfig()
{
loadConfigFile();
}
public static watermarkConfig GetInstance()
{
if (instance == null )
{
instance = new watermarkConfig();
}
return instance;
}
private void loadConfigFile()
{
string configFile = HttpContext.Current.Request.ApplicationPath + " /config/photo/photo.config " ;
XmlDocument xml = new XmlDocument();
xml.Load(HttpContext.Current.Server.MapPath(configFile));
XmlNode waterroot = xml.SelectSingleNode( " picture/watermark " );
this .isOpen = waterroot.Attributes[ " isOpen " ].Value;
this .filePath = waterroot.Attributes[ " filePath " ].Value;
this .padding = Convert.ToInt32(waterroot.Attributes[ " padding " ].Value);
foreach (XmlNode rule in waterroot.ChildNodes)
{
if (rule.NodeType != XmlNodeType.Comment)
{
if (rule.Name.ToLower().Equals( " rule " ))
{
rules.Add(rule.Attributes[ " urlfrom " ].Value);
}
}
}
}
}
/config/photo/photo.config 的内容
<!--水印设置,isOpen 1开启水印 其他值关闭,filePath 水印图片的物理路径, rule 包含哪些字符串的图片需要加水印-->
<watermark isOpen="1" filePath="~/watermark.png" padding="100">
<rule urlfrom="/photo/e0"></rule>
<rule urlfrom="/photo/f0"></rule>
<rule urlfrom="/photo/a0"></rule>
</watermark>