在其前导页设置Session,通过检查Session是否为空来判断用户是否是通过正常途径下载的。
<location path="download"> <system.web> <httpHandlers> <add verb="*" path="*.*" type="ForbiddenThief"/> </httpHandlers> </system.web> </location>
using System;using System.Data;using System.Configuration;susing System.Web;using System.Web.Security;using System.Web.SessionState;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.WebControls.WebParts;using System.Web.UI.HtmlControls;using System.IO;
/// <summary>/// 用于实现防盗链的HttpHandler,本实例中是通过Session中来判断用户是否非本站链接下载本站文件/// 主要要访问Session的话,我们的自定义类还必须实现System.Web.SessionState.IRequiresSessionState接口/// </summary>public class ForbiddenThief : IHttpHandler, System.Web.SessionState.IRequiresSessionState{ public ForbiddenThief() { }
#region IHttpHandler 成员
public bool IsReusable { get { return true; } }
public void ProcessRequest(HttpContext context) { HttpRequest request = context.Request; HttpResponse response = context.Response; string requestFile = request.PhysicalPath; HttpSessionState session = context.Session; //注意这里ForbiddenThief同时实现了两个接口IHttpHandler及IRequiresSessionState,要想访问Session必须要实现后一个接口 if (session["visited"] == null)//如果通过指定下面中的链接下载,就会设置Session["visited"]的值 { response.Write("请不要盗链本站资源,请从首页访问。<a href='index.aspx'>首页</a>"); } else//如果Session["visited"]为空表明用户没有通过正常途径访问本页面,即为盗链网站链接过来的 { if (File.Exists(requestFile)) { WriteFile(requestFile, response); } else { response.Write("你下载的文件不存在。<a href='index.aspx'>首页</a>"); } session.Remove("visited");//清除Session,保证用户下次下载还需要经过相关页面跳转 } } /// <summary> /// 向客户端输出文件 /// </summary> /// <param name="filePath">文件的完整物理路径</param> /// <param name="response">服务器响应对象的实例</param> private void WriteFile(string filePath,HttpResponse response) { string extension = Path.GetExtension(filePath).ToLower(); string contentType=GetMimeType(extension); response.Clear(); response.ContentType = contentType; string fileName = System.IO.Path.GetFileName(filePath); //下面的方法保证在客户端出现下载对话框而不是在浏览器中打开 response.AddHeader("Content-Disposition", "attachment;filename=" + fileName); response.WriteFile(filePath); }
/// <summary> /// 根据文件后缀来获取MIME类型字符串 /// </summary> /// <param name="extension">文件后缀</param> /// <returns></returns> public static string GetMimeType(string extension) { string mime = string.Empty; extension = extension.ToLower(); switch (extension) { case ".avi": mime = "video/x-msvideo"; break; case ".bin": mime = "application/octet-stream"; break; case ".exe": mime = "application/octet-stream"; break; case ".dll": mime = "application/octet-stream"; break; case ".class": mime = "application/octet-stream"; break; case ".csv": mime = "text/comma-separated-values"; break; case ".css": mime = "text/css"; break; case ".doc": mime = "application/msword"; break; case ".dot": mime = "application/msword"; break; case ".gz": mime = "application/gzip"; break; case ".gif": mime = "image/gif"; break; case ".jpeg": mime = "image/jpeg"; break; case ".jpg": mime = "image/jpeg"; break; case ".jpe": mime = "image/jpeg"; break; case ".mpeg": mime = "video/mpeg"; break; case ".mpg": mime = "video/mpeg"; break; case ".mpe": mime = "video/mpeg"; break; case ".mp3": mime = "audio/mpeg"; break; case ".pdf": mime = "application/pdf"; break; case ".rar": mime = "application/octet-stream"; break; case ".txt": mime = "text/plain"; break; case ".xls": mime = "application/msexcel"; break; case ".xla": mime = "application/msexcel"; break; case ".z": mime = "application/x-compress"; break; case ".zip": mime = "application/x-zip-compressed"; break; default: break; } return mime; }
#endregion}