在一些有图片的管理系统中,管理站点由于安全等因素,往往不和前台站点在一个服务器上.这时,要实现图片的管理站点上传,并在前台站点等多站点显示,我们一般会采用单独的图片服务器来实现.
为了使用方便,我们可以使用自定义控件,如一个文件上传控件,通过指定Ftp站点的相关信息,在文件上传时,自动上传到Ftp服务器.
而在前台显示时,也可以通过一个继承自Image的控件,从一个地址(图片服务器)来取得图片的缩略图.
在图片服务器, 我们可以写一个HttpHandler来实现生成缩略图的过程.
按照这个思路.上传文件时,代码举例如下:
HTML
<asp:FtpFileUpload style="display:block;" runat="server" ID="fuPicture" />

编码
string GetGifImageUrl()

{
//上传图片
if (this.fuPicture.HasFile)

{
//返回上传到Ftp服务器后的文件名
return this.fuPicture.Save();

}

return "";
}

web.config配置
<FtpFileUploadConfig Server="192.168.2.2" Port="21" UserName="scimg" Password="scimg@sina163.com" HomePath="" AllowExt=".jpe|.jpeg|.jpg|.png|.tif|.tiff|.bmp"/>

在显示图片时,代码举例如下:
<asp:RemoteImage runat="server" ID="imagePicture" ImageUrl='<%# OperData.Picture %>' />

web.config配置如下:
<RemoteImageConfig RemoteHomeUrl="http://img.xxxxxx.cn/getthumb.aspx" EnableThumb="true"/>

我们已经看到了使用,下面我们来实现它:
首先是FtpFileUpload控件的实现方法
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Configuration;
using System.Collections;
using System.Net;
using System.IO;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace Iyond.Web.UI.WebControls


{

/**//// <summary>
/// <section name="FtpFileUploadConfig" type="System.Configuration.SingleTagSectionHandler"/>
/// <FtpFileUploadConfig Server="192.168.2.192" Port="21" UserName="happyfen_images" Password="happyfen_images" HomePath="" >
/// </summary>
public class FtpFileUpload : FileUpload

{
protected FtpFileUploadConfig config = new FtpFileUploadConfig();

private static Regex regexName = new Regex(@"[^\s]*$", RegexOptions.Compiled);


/**//// <summary>
/// 检查文件是否存在
/// </summary>
/// <param name="parentPath">父目录</param>
/// <param name="name">文件名</param>
/// <returns></returns>
protected bool CheckFileOrPath(string parentPath, string fileName)

{
//检查一下日期目录是否存在
FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(config.GetFtpUri(parentPath));
req.Credentials = config.Credentials;
req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

Stream stream = req.GetResponse().GetResponseStream();

using (StreamReader sr = new StreamReader(stream))

{
string line = sr.ReadLine();
while (!string.IsNullOrEmpty(line))

{
GroupCollection gc = regexName.Match(line).Groups;
if (gc.Count != 1)

{
throw new ApplicationException("FTP 返回的字串格式不正确");
}

string path = gc[0].Value;
if (path == fileName)

{
return true;
}

line = sr.ReadLine();
}
}

return false;

}

protected void CreatePath(string parentPath, string name)

{
FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(config.GetFtpUri(string.Format("{0}/{1}",parentPath,name)));
req.Credentials = config.Credentials;
req.Method = WebRequestMethods.Ftp.MakeDirectory;
req.GetResponse();
}


/**//// <summary>
/// 在Ftp服务器上保存文件,并返回文件名
/// </summary>
/// <returns>保存的文件名以及路径</returns>
/// <remarks>
/// 必须在 app.config 中配置
/// </remarks>
public string Save()

{
if (!this.HasFile)
return string.Empty;

if (config.AllowExt.IndexOf(Path.GetExtension(this.FileName)) == -1)
throw new ApplicationException("不允许的文件类型" + Path.GetExtension(this.FileName));
//检查一下日期目录是否存在
string dayPath = DateTime.Today.ToString("yyyyMMdd");
if (!this.CheckFileOrPath("", dayPath))

{
this.CreatePath("", dayPath);
}

string fileName = string.Format("{0}_{1}{2}",Path.GetFileNameWithoutExtension(this.FileName),
DateTime.Now.TimeOfDay.TotalMilliseconds,
Path.GetExtension(this.FileName));

string filePath = string.Format("{0}/{1}",
dayPath, fileName
);

FtpWebRequest req = (FtpWebRequest)FtpWebRequest.Create(config.GetFtpUri(filePath));
req.Credentials = config.Credentials;
req.Method = WebRequestMethods.Ftp.UploadFile;
//这么效率应该高点了吧
BufferedStream upstream = new BufferedStream(req.GetRequestStream());
for (int byteData = this.FileContent.ReadByte(); byteData != -1; byteData = this.FileContent.ReadByte())
{
upstream.WriteByte((byte)byteData);
}
upstream.Flush();

upstream.Close();
req.GetResponse();

return filePath;

}

}

public class FtpFileUploadConfig

{
private IDictionary config = ConfigurationManager.GetSection("FtpFileUploadConfig") as IDictionary;


/**//// <summary>
/// FTP服务器IP
/// </summary>
public string Server

{
get

{
return config["Server"].ToString();
}
}


/**//// <summary>
/// FTP服务器端口
/// </summary>
public string Port

{
get

{
return config["Port"].ToString();
}
}


/**//// <summary>
/// FTP服务器登陆用户名
/// </summary>
public string UserName

{
get

{
return config["UserName"].ToString();
}
}


/**//// <summary>
/// Ftp服务器登陆密码
/// </summary>
public string Password

{
get

{
return config["Password"].ToString();
}
}


/**//// <summary>
/// 上传的主目录,每个上传的文件建立日期(例:20070203)的目录
/// </summary>
public string HomePath

{
get

{
return config["HomePath"].ToString();
}
}


/**//// <summary>
/// AllowExt = ".jpe|.jpeg|.jpg|.png|.tif|.tiff|.bmp"
/// </summary>
public string AllowExt

{
get

{
return config["AllowExt"].ToString();
}
}


/**//// <summary>
/// 依配置,生成FTP的URI
/// </summary>
/// <param name="relationFilePath"></param>
/// <returns></returns>
public Uri GetFtpUri(string relationFilePath)

{

string uriString = string.Empty;
if (HomePath != "")

{
uriString = string.Format("ftp://{0}:{1}/%2f{2}/{3}", Server, Port, HomePath, relationFilePath);
}
else

{
uriString = string.Format("ftp://{0}:{1}/%2f{2}", Server, Port, relationFilePath);
}
Uri uri = new Uri(uriString);

return uri;

}


/**//// <summary>
/// 依配置,返回ICredentials的实例
/// </summary>
public ICredentials Credentials

{
get

{
return new NetworkCredential(UserName, Password);
}
}



}


}

然后是RemoteImage控件的实现
using System;
using System.Collections.Generic;
using System.Collections;
using System.Configuration;
using System.Web;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Web.UI.WebControls;

namespace Iyond.Web.UI.WebControls


{
public class RemoteImageHandler : IHttpHandler

{
protected HttpContext context = null;
static Hashtable htmimes = new Hashtable();
internal readonly string AllowExt = ".jpe|.jpeg|.jpg|.png|.tif|.tiff|.bmp";


IHttpHandler Members#region IHttpHandler Members

public bool IsReusable

{

get
{ return false; }
}

public void ProcessRequest(HttpContext context)

{
this.context = context;
htmim