web.config配置
<FtpFileUploadConfig Server="192.168.2.2" Port="21" UserName="scimg" Password="[email protected]" 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;
Stream upstream = req.GetRequestStream();
for (int byteData = this.FileContent.ReadByte(); byteData != -1; byteData = this.FileContent.ReadByte())
{
upstream.WriteByte((byte)byteData);
}
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;
htmimes[".jpeg"] = "image/jpeg";
htmimes[".jpg"] = "image/jpeg";
htmimes[".png"] = "image/png";
htmimes[".tif"] = "image/tiff";
htmimes[".tiff"] = "image/tiff";
htmimes[".bmp"] = "image/bmp";
try
{
string image = context.Request.QueryString["img"];
int width = Convert.ToInt32(context.Request.QueryString["w"]);
int height = Convert.ToInt32(context.Request.QueryString["h"]);
string imagePath = context.Request.MapPath(image);
if (!File.Exists(imagePath))
{
context.Response.End();
return;
}
else if (width == 0 && height == 0)
{
context.Response.Redirect(image);
}
else
{
string imageUrl = GetPicPathUrl(image, width, height);
context.Response.Redirect(imageUrl);
}
}
catch
{
context.Response.End();
}
}
#endregion
Helper#region Helper
/**//// <summary>
/// 获取图像编码解码器的所有相关信息
/// </summary>
/// <param name="mimeType">包含编码解码器的多用途网际邮件扩充协议 (MIME) 类型的字符串</param>
/// <returns>返回图像编码解码器的所有相关信息</returns>
static ImageCodecInfo GetCodecInfo(string mimeType)
{
ImageCodecInfo[] CodecInfo = ImageCodecInfo.GetImageEncoders();
foreach (ImageCodecInfo ici in CodecInfo)
{
if (ici.MimeType == mimeType) return ici;
}
return null;
}
/**//// <summary>
/// 检测扩展名的有效性
/// </summary>
/// <param name="sExt">文件名扩展名</param>
/// <returns>如果扩展名有效,返回true,否则返回false.</returns>
bool CheckValidExt(string sExt)
{
bool flag = false;
string[] aExt = AllowExt.Split('|');
foreach (string filetype in aExt)
{
if (filetype.ToLower() == sExt)
{
flag = true;
break;
}
}
return flag;
}
/**//// <summary>
/// 保存图片
/// </summary>
/// <param name="image">Image 对象</param>
/// <param name="savePath">保存路径</param>
/// <param name="ici">指定格式的编解码参数</param>
void SaveImage(System.Drawing.Image image, string savePath, ImageCodecInfo ici)
{
string path = new FileInfo(savePath).DirectoryName;
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
//设置 原图片 对象的 EncoderParameters 对象
EncoderParameters parameters = new EncoderParameters(1);
parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, ((long)90));
image.Save(savePath, ici, parameters);
parameters.Dispose();
}
#endregion
Methods#region Methods
/**//// <summary>
/// 生成缩略图
/// </summary>
/// <param name="sourceImagePath">原图片路径(相对路径)</param>
/// <param name="thumbnailImagePath">生成的缩略图路径,如果为空则保存为原图片路径(相对路径)</param>
/// <param name="thumbnailImageWidth">缩略图的宽度(高度与按源图片比例自动生成)</param>
public void ToThumbnailImages(string sourceImagePath, string thumbnailImagePath, int nWidth, int nHeight)
{
string sExt = sourceImagePath.Substring(sourceImagePath.LastIndexOf(".")).ToLower();
if (sourceImagePath.ToString() == System.String.Empty) throw new NullReferenceException("sourceImagePath is null!");
if (!CheckValidExt(sExt))
{
throw new ArgumentException("原图片文件格式不正确,支持的格式有[ " + AllowExt + " ]", "sourceImagePath");
}
//从 原图片 创建 Image 对象
System.Drawing.Image image = System.Drawing.Image.FromFile(sourceImagePath);
//int num = ((thumbnailImageWidth / 4) * 3);
int width = image.Width;
int height = image.Height;
if (nWidth == 0)
{
nWidth = width;
}
if (nHeight == 0)
{
nHeight = height;
}
//计算图片的比例
double nblh = image.Width * 1.0 / nWidth;
double nblv = image.Height * 1.0 / nHeight;
double nBL = Math.Max(nblh, nblv);// nblh > nblv ? nblh:nblv;
int thumbWidth, thumbHeight;
if (nBL > 1.0)
{
thumbWidth = (int)(image.Width / nBL);
thumbHeight = (int)(image.Height / nBL);
}
else
{
thumbWidth = nWidth;
thumbHeight = nHeight;
}
//用指定的大小和格式初始化 Bitmap 类的新实例
Bitmap bitmap = new Bitmap(thumbWidth, thumbHeight, PixelFormat.Format32bppArgb);
//从指定的 Image 对象创建新 Graphics 对象
Graphics graphics = Graphics.FromImage(bitmap);
//清除整个绘图面并以透明背景色填充
graphics.Clear(Color.Transparent);
//在指定位置并且按指定大小绘制 原图片 对象
graphics.DrawImage(image, new Rectangle(0, 0, thumbWidth, thumbHeight));
image.Dispose();
try
{
//将此 原图片 以指定格式并用指定的编解码参数保存到指定文件
string savepath = (thumbnailImagePath == null ? sourceImagePath : thumbnailImagePath);
SaveImage(bitmap, savepath, GetCodecInfo((string)htmimes[sExt]));
}
catch (System.Exception e)
{
throw e;
}
finally
{
bitmap.Dispose();
graphics.Dispose();
}
}
#endregion
public string GetPicPathUrl(string image, int nWidth, int nHeight)
{
const string pathEnd = "_";
if (nWidth == 0 || nHeight == 0)
{
return image;
}
string imageSmallUrl = string.Format("{0}{1}/{2}_{3}{4}", image, pathEnd, nWidth, nHeight, Path.GetExtension(image));
string imagePath = context.Request.MapPath(image);
string imageSmallPath = context.Request.MapPath(imageSmallUrl);
if (!File.Exists(imageSmallPath))
{
this.ToThumbnailImages(imagePath, imageSmallPath, nWidth, nHeight);
}
return imageSmallUrl;
}
}
public class RemoteImage : System.Web.UI.WebControls.Image
{
protected RemoteImageConfig config = new RemoteImageConfig();
protected Unit width = Unit.Empty;
protected Unit height = Unit.Empty;
public override string ImageUrl
{
get
{
if (this.DesignMode)
{
return base.ImageUrl;
}
else if (config.EnableThumb &&
this.Width.Type == UnitType.Pixel && this.Height.Type == UnitType.Pixel)
{
return string.Format("{0}?img={1}&w={2}&h={3}", config.RemoteHomeUrl, System.Web.HttpUtility.UrlEncode(base.ImageUrl),
this.Width.IsEmpty ? 0 : this.Width.Value, this.Height.IsEmpty ? 0 : this.Height.Value);
}
else
{
return string.Format("{0}/{1}", config.RemoteHomeUrl, base.ImageUrl);
}
}
set
{
base.ImageUrl = value;
}
}
/**//// <summary>
/// 宽度,最好指定象素单位,Image服务器会生成相应宽度的缩略图
/// </summary>
public override Unit Width
{
get
{
return width;
}
set
{
width = value;
}
}
/**//// <summary>
/// 高度,最好指定象素单位,Image服务器会生成相应高度的缩略图
/// </summary>
public override Unit Height
{
get
{
return height;
}
set
{
height = value;
}
}
}
public class RemoteImageConfig
{
private IDictionary config = ConfigurationManager.GetSection("RemoteImageConfig") as IDictionary;
/**//// <summary>
/// 图片服务器HttpHandler地址
/// </summary>
public string RemoteHomeUrl
{
get
{
return config["RemoteHomeUrl"].ToString().TrimEnd('\\','/');
}
}
//是否启用缩略图
public bool EnableThumb
{
get
{
return Convert.ToBoolean(config["EnableThumb"]);
}
}
}
}