正文

如何将论坛附件直接以文件形式保存,并读取照片文件的Exif信息2006-05-19 11:42:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/Csharpsky/14341.html

分享到:

废话少说,直接进入主题:      准备工作:下载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字段,因为我们不再需要他了。      完工!    

阅读(4273) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册