废话少说,直接进入主题: 准备工作:下载PhotoProperties类库(http://www.codeproject.com/cs/media/photoproperties.asp),用于读取Exif信息,在Components中引用该类库1、修改web.config配置文件,在forums/forums下增加一个配置项 uploadFilesPath="/Upload/" 值可以自行修改,用来保存用户上传的文件;2、修改数据库 forums_PostAttachments表增加如下字段 DiskFileName nvarchar(256), 保存附件在硬盘上的文件名 Exif nvarchar(200), 用于保存照片附件的Exif信息 CheckGuid nvarchar(50) 用于保存检测的Guid 注意:我们修改的最终方案是会删除原有的Content字段的 修改存储过程:create procedure forums_PostAttachment_Add ( @PostID int, @UserID int, @ForumID int, @Filename nvarchar(256), @DiskFileName nvarchar(256), @ContentType nvarchar(50), @ContentSize int, @Exif nvarchar(500), @CheckGuid nvarchar(50))ASBEGIN IF EXISTS (SELECT PostID FROM forums_PostAttachments WHERE PostID = @PostID) RETURN INSERT INTO forums_PostAttachments ( PostID, ForumID, UserID, [FileName], DiskFileName, ContentType, ContentSize, Exif, CheckGuid ) VALUES ( @PostID, @ForumID, @UserID, @Filename, @DiskFileName, @ContentType, @ContentSize, @Exif, @CheckGuid )ENDGOSET QUOTED_IDENTIFIER OFF GOSET ANSI_NULLS ON GOSET QUOTED_IDENTIFIER ON GOSET ANSI_NULLS ON GO 3、修改系统配置管理类Components项目下的Configuration/ForumConfiguration.cs文件: 1)在头部增加一变量string uploadFilesPath="/Upload/"; 2)在LoadValuesFromConfigurationXml方法里增加以下代码,读取配置文件中的值: uploadFilesPath = attributeCollection["uploadFilesPath"].Value; 3)给ForumConfiguration类增加UploadFilesPath属性: public string UploadFilesPath { get { return uploadFilesPath; } } 配置文件部分完成。4、修改Components项目下的PostAttachment类 增加如下引用:using System.IO;using JSG.PhotoPropertiesLibrary; 增加如下变量: string exif;string diskFileName; string checkGuid; 增加如下方法: /**//// <summary> /// 获取文件的Exif信息 /// </summary> /// <param name="postedFile"></param> /// <returns></returns> private string GetExif(string ContentType,string FullFileName) { string imgFilePath = FullFileName; string exif=""; try { PhotoProperties pp = new PhotoProperties(); pp.Initialize(); pp.Analyze(imgFilePath); if(ContentType.ToLower() == "image/pjpeg") { //Exif Version exif += "Exif版本:" + pp.GetTagDatum(36864).PrettyPrintValue; //制造商 exif += " 制造商:" + pp.GetTagDatum(271).PrettyPrintValue; //型号 exif += " 型号:" + pp.GetTagDatum(272).PrettyPrintValue; //拍摄时间 exif += " 拍摄时间:" + pp.GetTagDatum(36868).PrettyPrintValue; //暴光时间: exif += "<BR>暴光时间:" + pp.GetTagDatum(33434).PrettyPrintValue + "秒"; //光圈 exif += " 光圈:" + pp.GetTagDatum(33437).PrettyPrintValue; //ISO exif += " ISO:" + pp.GetTagDatum(34855).PrettyPrintValue; //分辨率 exif += " 分辨率:" + pp.GetTagDatum(282).PrettyPrintValue + "/" + pp.GetTagDatum(283).PrettyPrintValue; } } catch{} return exif; } 在构造函数的最下面增加:string uploadPath = HttpContext.Current.Server.MapPath("~" + AspNetForums.Configuration.ForumConfiguration.GetConfig().UploadFilesPath); uploadPath += "\" + Users.GetUser().UserID.ToString() + "\"; if(!System.IO.Directory.Exists(uploadPath)) { System.IO.Directory.CreateDirectory(uploadPath); } //HttpContext.Current.User.Identity diskFileName = System.Guid.NewGuid().ToString() + System.IO.Path.GetExtension(postedFile.FileName); uploadPath += diskFileName; postedFile.SaveAs(uploadPath);exif = GetExif(contentType,uploadPath);checkGuid = System.Guid.NewGuid().ToString(); 最后增加3个属性,代码如下: /**//// <summary> /// 磁盘文件名(文件保存在硬盘上的物理文件名) /// 37AE8655-05F8-4ed9-A771-35B41F0222DE.ext /// </summary> public string DiskFileName { get { return diskFileName; } set { diskFileName = value; } } /**//// <summary> /// 照片Exif信息 /// </summary> public string Exif { get { return exif; } set { exif = value; } } /**//// <summary> /// 用于判断是否要以attachment形式让用户下载附件 /// </summary> public string CheckGuid { get { return checkGuid; } set { checkGuid = value; } }5、下面要修改的是负责系统数据库操作的SqlDataProvider项目,用于完成对新增加字段的数据库操作,修改如下: 找到public override void AddPostAttachment(Post post, PostAttachment attachment)方法: //增加DiskFileName字段,用于附件在硬盘上的保存文件名,//类似1990ffb3-3992-4438-b7e2-2bca963d969f.jpg//该文件名不暴露给最终用户myCommand.Parameters.Add("@DiskFileName", SqlDbType.NVarChar, 256).Value = attachment.DiskFileName;//注释掉对Content的操作//myCommand.Parameters.Add("@Content", SqlDbType.Image).Value = attachment.Content;//增加照片Exif信息与用于验证的CheckGuid字段myCommand.Parameters.Add("@Exif",SqlDbType.NVarChar,500).Value = attachment.Exif;myCommand.Parameters.Add("@CheckGuid",SqlDbType.NVarChar,500).Value = attachment.CheckGuid; 注意:这里需要注释掉对Content字段的操作,因为虽然数据字段还在,但上面修改的存储过程中,我们已经删除了对Content字段的操作;6、修改Components项目下的ForumsDataProvider类中的PopulatePostAttachmentFromIReader方法,完成从数据库到对象的转换,修改如下: //删除Content字段,附件内容不再保存到数据库,而是直接以文件形式保存到硬盘// attachment.Content = (byte[]) reader["Content"];//增加DiskFileName字段,用于附件在硬盘上的保存文件名,//类似1990ffb3-3992-4438-b7e2-2bca963d969f.jpg//该文件名不暴露给最终用户attachment.DiskFileName = (string) reader["DiskFileName"].ToString();//增加照片Exif信息与用于验证的CheckGuid字段if(reader["Exif"] != DBNull.Value){ attachment.Exif = (string) reader["Exif"];}attachment.CheckGuid = (string) reader["CheckGuid"].ToString();7、到此数据的操作部分已经都完成了,下面要做的就是修改显示部分,系统最终显示帖子内容是通过Controls下的TextPost类完成的,我们要修改的代码当然也在这里了。 找到InitializeSkin方法中的body.Text = post.FormattedBody;,在他下面增加如下代码: //判断附件的mime类型是否为图片,如果为图片,那么直接调用DisplayImage方法生成显示图片的HTML代码 //此处可扩充直接显示附件为Flash等其他类型的文件 string Attachment=post.AttachmentFilename; if (Attachment!="" && Attachment!=null) { AspNetForums.Components.PostAttachment attachment = Posts.GetAttachment(post.PostID); string contentType = attachment.ContentType; if (contentType=="image/pjpeg" || contentType=="image/gif" || contentType=="image/bmp" || contentType=="image/x-png" ) { body.Text += DisplayImage(Globals.GetSiteUrls().PostAttachment(post.PostID) + "&guid=" + attachment.CheckGuid); //显示Exif信息 if(attachment.Exif.Length>0) { body.Text += "<span class=exif>" + attachment.Exif + "</span>"; } } } DisplayImage方法很简单,代码如下,自己可以修改该代码,给图片增加边框等 /**//// <summary>/// 如果附件为图片类型,那么调用该方法,生成显示图片的HTML代码/// </summary>/// <param name="ImageFilePath">要显示的图片路径</param>/// <returns></returns>public string DisplayImage(string ImageFilePath) { return "<a href='" + ImageFilePath + "' target='_blank'><img src="" + ImageFilePath + "" border=0></a>"; }8、修改附件下载部分,Controls项目下的DownloadPostAttachment类,代码如下: System.Web.HttpContext.Current.Response.Clear(); System.Web.HttpContext.Current.Response.ContentType = attachment.ContentType; //判断用户从QueryString提交的Guid值是否和数据库的CheckGuid是否相同 //如果相同,那么不以attachment的形式输出,直接显示文件(通常提供该Guid值的情况都是为图片附件) //如果不同,那么以attachment形式输出,直接由用户下载 if(forumContext.CheckGuid != attachment.CheckGuid) { System.Web.HttpContext.Current.Response.AppendHeader("content-disposition", "attachment; filename="" + System.Web.HttpUtility.UrlEncode(attachment.FileName,System.Text.Encoding.UTF8) + """); } //System.Web.HttpContext.Current.Response.OutputStream.Write(attachment.Content, 0, attachment.Length); string diskFileName = System.Web.HttpContext.Current.Server.MapPath("~/" + AspNetForums.Configuration.ForumConfiguration.GetConfig().UploadFilesPath + "/" + attachment.UserID.ToString() + "/" + attachment.DiskFileName); System.Web.HttpContext.Current.Response.WriteFile(diskFileName); System.Web.HttpContext.Current.Response.End();9、最后要修改的是ForumContext类,要对该类增加一个属性,用于读取通过QueryString传递的Guid值,找到Components项目下的ForumContext类, 首先增加一变量: string checkGuid = ""; 在构造函数的最下面增加: checkGuid = context.Request.QueryString["guid"]; 在最下面增加属性: //CheckGuid 判断是否合法的显示文件请求public string CheckGuid { get { return checkGuid; } }至此,我们的修改工作已经全部完成,下面要做的就是对原有的数据库进行升级,将Content字段中的数据保存到硬盘,下面的代码比较简单了,直接贴出代码 在web项目下增加一个页面,后台的操作代码如下,代码比较简单,都是直接操作数据库的。不要忘记增加对PhotoProperties的引用, using System;using System.Collections;using System.ComponentModel;using System.Data;using System.Data.SqlClient;using System.Drawing;using System.Web;using System.Web.SessionState;using System.Web.UI;using System.Web.UI.WebControls;using System.Web.UI.HtmlControls;using System.IO;using JSG.PhotoPropertiesLibrary;namespace AspNetForums.Update{ /**//// <summary> /// update_20040807 的摘要说明。 /// </summary> public class update_20040807 : System.Web.UI.Page { protected System.Web.UI.WebControls.Button Button1; private void Page_Load(object sender, System.EventArgs e) { // 在此处放置用户代码以初始化页面 } Web 窗体设计器生成的代码#region Web 窗体设计器生成的代码 override protected void OnInit(EventArgs e) { // // CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。 // InitializeComponent(); base.OnInit(e); } /**//// <summary> /// 设计器支持所需的方法 - 不要使用代码编辑器修改 /// 此方法的内容。 /// </summary> private void InitializeComponent() { this.Button1.Click += new System.EventHandler(this.Button1_Click); this.Load += new System.EventHandler(this.Page_Load); } #endregion private void Button1_Click(object sender, System.EventArgs e) { string ConnectionString = "database=forums;server=dbserver;User ID=sa;Password=;"; SqlConnection myConn = new SqlConnection(ConnectionString); myConn.Open(); string select="select * from forums_PostAttachments"; SqlCommand myComm = new SqlCommand(select,myConn); SqlDataReader dr = myComm.ExecuteReader(); string DiskFileName,CheckGuid,Exif; string UpdateString="Update forums_PostAttachments SET DiskFileName='{0}',Exif='{1}',CheckGuid='{2}' where PostID={3}"; string UserID; byte[] fileContent; FileStream fs=null; SqlConnection myConn2 = new SqlConnection(ConnectionString); myConn2.Open(); while(dr.Read()) { UserID=dr["UserID"].ToString(); fileContent = (byte[])dr["Content"]; DiskFileName = Server.MapPath("~/" + AspNetForums.Configuration.ForumConfiguration.GetConfig().UploadFilesPath + "/" + UserID + "/" + System.Guid.NewGuid().ToString()) + System.IO.Path.GetExtension(dr["FileName"].ToString()); CheckGuid = System.Guid.NewGuid().ToString(); fs=new FileStream(DiskFileName ,FileMode.Create,FileAccess.Write, FileShare.ReadWrite); fs.Write(fileContent,0,fileContent.Length); fs.Close(); Exif = GetExif(DiskFileName); SqlCommand myComm2 = new SqlCommand(string.Format(UpdateString,System.IO.Path.GetFileName(DiskFileName),Exif,CheckGuid,dr["PostID"].ToString()),myConn2); myComm2.ExecuteNonQuery(); } dr.Close(); } private string GetExif(string diskFileName) { string imgFilePath = diskFileName; PhotoProperties pp = new PhotoProperties(); string exif=""; try { pp.Initialize(); pp.Analyze(imgFilePath); //Exif Version exif += "Exif版本:" + pp.GetTagDatum(36864).PrettyPrintValue; //制造商 exif += " 制造商:" + pp.GetTagDatum(271).PrettyPrintValue; //型号 exif += " 型号:" + pp.GetTagDatum(272).PrettyPrintValue; //拍摄时间 exif += " 拍摄时间:" + pp.GetTagDatum(36868).PrettyPrintValue; //暴光时间: exif += "<BR>暴光时间:" + pp.GetTagDatum(33434).PrettyPrintValue + "秒"; //光圈 exif += " 光圈:" + pp.GetTagDatum(33437).PrettyPrintValue; //ISO exif += " ISO:" + pp.GetTagDatum(34855).PrettyPrintValue; //分辨率 exif += " 分辨率:" + pp.GetTagDatum(282).PrettyPrintValue + "/" + pp.GetTagDatum(283).PrettyPrintValue; } catch{} return exif; } }} 别忘了最后一步工作,删除forums_PostAttachments表中的Content字段,因为我们不再需要他了。 完工!

评论