image images image

一、摘要

对于你自己网站上的图片,你可能会希望它们只显示在自己网站的页面上,而当别人的网站引用它们时,不给予显示 image ,或者显示一张自定义的警告图片 images ,或者在图片上加上一个水印信息 image ,告诉浏览者此图片是来自你的网站的。

使用ASP.NET的HttpHandler可以很方便地达到这样的效果。

二、实现步骤

1. 在网站项目中添加一个类文件,实现IHttpHandler接口

2. 配置Web.Config,将图片文件的请求映射到第1步中的类处理程序

下面先讲第1步配置Web.Config,再讲第1步。因为配置非常简单,而类文件则需要一些代码,将会分三种情况给出这个类文件的三个版本。

三、配置Web.Config详解

假设第1步的类文件命名为ImageGuardHandler.cs,该文件定义了一个位于命名空间 zizhujy.HttpHandlers 下的类 ImageGuardHandler。现在配置Web.Config,使得图片文件请求被转交到ImageGuardHandler来处理。

如果网站服务器是使用的IIS 7.5或以上,则只需按如下格式配置:

<?xml version="1.0" encoding="utf-8"?>
<!--
  有关如何配置 ASP.NET 应用程序的详细信息,请访问
  http://go.microsoft.com/fwlink/?LinkId=152368
  -->

<configuration> ... <system.webServer> <validation validateIntegratedModeConfiguration="false"/> <modules runAllManagedModulesForAllRequests="true"/> <handlers> <add name="ImageGuardHandlerPng" path=".png" verb="" type="zizhujy.HttpHandlers.ImageGuardHandler, zizhujy" resourceType="Unspecified" preCondition="integratedMode"/> <add name="ImageGuardHandlerGif" path=".gif" verb="" type="zizhujy.HttpHandlers.ImageGuardHandler, zizhujy" resourceType="Unspecified" preCondition="integratedMode"/> <add name="ImageGuardHandlerJpg" path=".jpg" verb="" type="zizhujy.HttpHandlers.ImageGuardHandler, zizhujy" resourceType="Unspecified" preCondition="integratedMode"/> </handlers> </system.webServer> ... </configuration>

如上,配置了对于三种图片文件(.png, .gif, .jpg)的请求,将会被ImageGuardHandler处理。

如果使用的是 IIS 5.1,则需要按如下格式配置:

<?xml version="1.0" encoding="utf-8"?>
<!--
  有关如何配置 ASP.NET 应用程序的详细信息,请访问
  http://go.microsoft.com/fwlink/?LinkId=152368
  -->

<configuration>
	...
    <system.web>
        <httpHandlers>
            <add path="*.gif" verb="*" type="zizhujy.HttpHandlers.ImageGuardHandler, zizhujy" validate="false"/>
            <add path="*.png" verb="*" type="zizhujy.HttpHandlers.ImageGuardHandler, zizhujy" validate="false"/>
            <add path="*.jpg" verb="*" type="zizhujy.HttpHandlers.ImageGuardHandler, zizhujy" validate="false"/>
        </httpHandlers>
    </system.web>
	...
</configuration>

四、处理程序ImageGuardHandler详解

1. 对于来自非本网站的图片请求给予拒绝服务的响应:

image

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using zizhujy.Utility;

namespace zizhujy.HttpHandlers
{
    public class ImageGuardHandler : IHttpHandler
    {
        public void ProcessRequest(System.Web.HttpContext context)
        {
            HttpResponse response = context.Response;
            HttpRequest request = context.Request;
            string imagePath = null;

            // Check whether the page requesting the image is from your site.
            if (request.UrlReferrer != null)
            {
                // Perform a case-insensitive comparison of the referer.
                if (string.Compare(request.Url.Host, request.UrlReferrer.Host, true, CultureInfo.InvariantCulture) == 0)
                {
                    // The requesting host is correct.
                    // Allow the image to be served(if it exists).
                    imagePath = request.PhysicalPath;
                    if (!File.Exists(imagePath))
                    {
                        response.Status = "Image not found";
                        response.StatusCode = 404;
                        return;
                    }
                }
            }

            if (imagePath == null)
            {
                response.Status = "Not allowed";
                response.StatusCode = 500;
                return;
            }

            // Set the content type to the appropriate image type.
            response.ContentType = "image/" + Path.GetExtension(imagePath).ToLower();

            // Serve the image.
            response.WriteFile(imagePath);
            //Image image = Image.FromFile(imagePath);
            //image = ImageHandler.WatermarkHandler.AddCopyrightText(image, "www.zizhujy.com", ImageHandler.CopyrightPosition.BottomRight);
            //image.Save(response.OutputStream, GetImageFormatByExtension(Path.GetExtension(imagePath)));

            //image.Dispose();
        }

        public bool IsReusable
        {
            get { return true; }
        }
    }
}

2. 对于来自非本网站的图片请求,显示一张自定义的警告图片,这个警告图片的路径可以配置在Web.Config中的 节中,如:

images

<?xml version="1.0" encoding="utf-8"?>
<!--
  有关如何配置 ASP.NET 应用程序的详细信息,请访问
  http://go.microsoft.com/fwlink/?LinkId=152368
  -->

<configuration> ... <appSettings> <httpHandlers> <add key="NotAllowedImage" value="~/Content/Images/NotAllowed.gif"/> </httpHandlers> </appSettings> ... </configuration>

ImageGuardHandler.cs代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using zizhujy.Utility;

namespace zizhujy.HttpHandlers { public class ImageGuardHandler : IHttpHandler { public void ProcessRequest(System.Web.HttpContext context) { HttpResponse response = context.Response; HttpRequest request = context.Request; string imagePath = null;

        // Check whether the page requesting the image is from your site.
        if (request.UrlReferrer != null)
        {
            // Perform a case-insensitive comparison of the referer.
            if (string.Compare(request.Url.Host, request.UrlReferrer.Host, true, CultureInfo.InvariantCulture) == 0)
            {
                // The requesting host is correct.
                // Allow the image to be served(if it exists).
                imagePath = request.PhysicalPath;
                if (!File.Exists(imagePath))
                {
                    response.Status = &quot;Image not found&quot;;
                    response.StatusCode = 404;
                    return;
                }
            }
        }

        if (imagePath == null)
        {
            // No valid image was allowed.
            // Return the warning image instead of the requested image.
            // Rather than hard-code this image, you could retrieve it from the web.config file (using the <appsettings> section or a custom section).

            //imagePath = context.Server.MapPath(&quot;~/Images/notAllowed.gif&quot;);
            imagePath = context.Server.MapPath(System.Configuration.ConfigurationManager.AppSettings.Get(&quot;NotAllowedImage&quot;).ToString());
        }

        // Set the content type to the appropriate image type.
        response.ContentType = &quot;image/&quot; + Path.GetExtension(imagePath).ToLower();

        // Serve the image.
        response.WriteFile(imagePath);
        //Image image = Image.FromFile(imagePath);
        //image = ImageHandler.WatermarkHandler.AddCopyrightText(image, &quot;www.zizhujy.com&quot;, ImageHandler.CopyrightPosition.BottomRight);
        //image.Save(response.OutputStream, GetImageFormatByExtension(Path.GetExtension(imagePath)));

        //image.Dispose();
    }

    public bool IsReusable
    {
        get { return true; }
    }
}

}

3. 对于来自非本网站的图片请求,在图片上加上一行水印文本,将自己网站的Url信息写在图片上。

image

这里涉及到给图片添加水印的程序,由于之前介绍过给图片添加水印的类库,这里就直接引用了它来完成添加水印的过程。在图片上添加水印的原理请见:

使用.NET的GDI+技术给图片加水印

ImageGuardHandler.cs文件源码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using zizhujy.Utility;

namespace zizhujy.HttpHandlers
{
    public class ImageGuardHandler : IHttpHandler
    {
        public void ProcessRequest(System.Web.HttpContext context)
        {
            HttpResponse response = context.Response;
            HttpRequest request = context.Request;
            string imagePath = null;

            // Check whether the page requesting the image is from your site.
            if (request.UrlReferrer != null)
            {
                // Perform a case-insensitive comparison of the referer.
                if (string.Compare(request.Url.Host, request.UrlReferrer.Host, true, CultureInfo.InvariantCulture) == 0)
                {
                    // The requesting host is correct.
                    // Allow the image to be served(if it exists).
                    imagePath = request.PhysicalPath;
                    if (!File.Exists(imagePath))
                    {
                        response.Status = "Image not found";
                        response.StatusCode = 404;
                        return;
                    }
                    else
                    {
                        // Serve the image normally
                        response.WriteFile(imagePath);
                        return;
                    }
                }
                else
                {
                    // Add watermark to the image
                    imagePath = request.PhysicalPath;

                    // Set the content type to the appropriate image type.
                    response.ContentType = "image/" + Path.GetExtension(imagePath).Replace(".", "").ToLower();

                    // Serve the image.
                    Image image = Image.FromFile(imagePath);

                    ImageHandler.TextWatermarker txtWatermarker = new ImageHandler.TextWatermarker(image, "www.zizhujy.com");
                    txtWatermarker.AddWatermark();

                    image = txtWatermarker.WatermarkedImage;
                    //image.Save(response.OutputStream, ImageHelper.GetImageFormatByExtension(Path.GetExtension(imagePath)));

                    MemoryStream mem = new MemoryStream();
                    image.Save(mem, ImageHelper.GetImageFormatByExtension(Path.GetExtension(imagePath)));

                    // Write the MemoryStream data to the OutputStream
                    mem.WriteTo(response.OutputStream);

                    mem.Dispose();

                    image.Dispose();
                    txtWatermarker.Dispose();
                    return;
                }
            }
            else
            {
                // Add watermark to the image
                imagePath = request.PhysicalPath;

                // Set the content type to the appropriate image type.
                response.ContentType = "image/" + Path.GetExtension(imagePath).Replace(".","").ToLower();

                // Serve the image.
                Image image = Image.FromFile(imagePath);
                ImageHandler.TextWatermarker txtWatermarker = new ImageHandler.TextWatermarker(image, "www.zizhujy.com");
                txtWatermarker.AddWatermark();
                image = txtWatermarker.WatermarkedImage;

                // If the image is in PNG format, then it can be saved into response.OutputStream directly 
                ImageFormat format = ImageHelper.GetImageFormatByExtension(Path.GetExtension(imagePath));
                //if (format.Equals(ImageFormat.Png))
                if (true)
                {
                    // Create the PNG in memory
                    MemoryStream mem = new MemoryStream();
                    image.Save(mem, ImageFormat.Png);

                    // Write the MemoryStream data to the output stream.
                    mem.WriteTo(response.OutputStream);
                    mem.Dispose();
                }
                else
                {
                    image.Save(response.OutputStream, format);
                }

                image.Dispose();
                txtWatermarker.Dispose();
                return;
            }
        }

        public bool IsReusable
        {
            get { return true; }
        }
    }
}

五、结语

以上三种版本的HttpHandler处理程序类,只需要任选其一即可。甚至可以整合成一个类,然后在Web.Config中作相关的配置,以控制其是直接拒绝服务,还是显示警告图片,或者是添加水印信息。

[donate: www.zizhujy.com]