正文

把图片文件存到数据库时, 在通过WEB页查询时动态生成2005-05-10 13:55:00

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

分享到:

需求是:
1.网站需要提供图片上传
2.图片不能用文件的方式保存, 只能保存到数据里.
3.查询页面里动态生成图像.

    一般都是用保存图片文件的方式, 在服务器上找个地方存下来, 然后数据库保存这个文件的WEB链接. 但是如果不允许用保存文件的方式, 而要求必须将图片数据直接存在数据库里呢?

    第一个问题是解决上传和保存的问题. 比如有一个网站提供DVD的资料, 用户可以自行加入新的DVD介绍文字和一个说明图片进去. 介绍和图片都放到数据库里, 文字资料不用说了, 主要是图片.
    以SQLSERVER为例:
    在SQLSERVER里建一个表来保存相关的信息,  如dvdimg,
CREATE TABLE [dbo].[DvdImg] (
     DVDID [int] NOT NULL ,
     Img [image] NULL ,
     filetype [char] (10)  NOT NULL
) ;
DVDid是关联到DVD主信息表的DVD唯一识别符, 为了让数据库快一点, 我把数据和图像分开了.
在上传页面上放一个文件上传控件,  就是下面这个东西:
protected System.Web.UI.HtmlControls.HtmlInputFile fEDImg;
名字就是: fEDImg
加一个保存按钮, 写个click事件的处理, 把数据insert到数据库里, 咱们主要说保存图片的这一段.
   
         if (this.fEDImg.PostedFile.ContentLength != 0)
              {
                 // 加入图片
                 int intDocLen = this.fEDImg.PostedFile.ContentLength;
                 byte[] Docbuffer = new byte[intDocLen];
  
                 Stream objStream;
  
                 objStream = this.fEDImg.PostedFile.InputStream;
  
                 objStream.Read(Docbuffer,0,intDocLen);
                 objStream.Close();
                 SqlConnection conn = Global.GetConn();
                  
                 SqlCommand cmd = conn.CreateCommand();
                 conn.Open();
                 cmd.CommandText = "delete from dvdimg where dvdid = "+dvd.DVDID.ToString();
                 cmd.ExecuteNonQuery();
  
  
                 int iLastIndex =this.fEDImg.PostedFile.FileName.LastIndexOf(".");
                 string sExtFileName = this.fEDImg.PostedFile.FileName.Substring(
                     iLastIndex + 1,
                     this.fEDImg.PostedFile.FileName.Length - iLastIndex -1
                     );
                  
                 cmd.CommandText ="insert into dvdimg (dvdid, img, filetype) values (@dvdid, @img, @filetype)";
                 cmd.CommandType = CommandType.Text;
                 cmd.Parameters.Add("@dvdid",SqlDbType.Int);
                 cmd.Parameters.Add("@img",SqlDbType.Image);
                 cmd.Parameters.Add("@filetype",SqlDbType.Char);
                 cmd.Parameters[0].Value =dvd.DVDID;
                 cmd.Parameters[1].Value = Docbuffer;
                 cmd.Parameters[2].Value = sExtFileName;
  
                 cmd.ExecuteNonQuery();
                 conn.Close();
  
             }

Global.GetConn()是得到数据库连接对象的方法, 我喜欢把这种全局性的东西放到这里. 不必多说.
这样一来, 图片就保存好了. 注意, 文件格式一定要保存, 不然以后就不知道这是什么东西了.

第二是浏览, 这里有一个问题, 就是图片数据是在数据库里,  而页面上显示图像时用的是<img>元素, 其中的src属性该如何写?
有人这么做: 把图片取出来之后, 生成一个临时文件, 然后把页面文件里的img的src指到这个文件里.
当然这样也可以解决问题, 但是有几个问题: 一是慢, 要写硬盘的, 二是临时文件什么时候删? 定期删吗? 网站访问量大了怎么办? 不好.

最好的解决办法是把img的src指向一个程序, 而不是一个文件, 由这个程序来生成图像, 向浏览器发送.
那么, 生成信息浏览页面时, 在显示画面的地方就可以这样写:
<img src=http://XXX.XXX.XXX/queryimg.aspx?dvdid=123>
向queryimg.aspx传一个参数, 也就是需要的DVD图像的编号.
然后, 可以新建一个queryimg.aspx页面文件, 记得, 一定要把page的Visible设为false, 这样页面的文件就不会出现了, 怎么输出都是靠你的程序.
然后在page_load里写下面一段这样的代码.
  
private void Page_Load(object sender, System.EventArgs e)
{
     // 在此处放置用户代码以初始化页面
     this.Visible = false;     
      
     int id = Convert.ToInt32( this.Request["id"]);
  
     sqlConnection1 = Global.GetConn();
     byte [] arImg;
     string sExtFileName;
     // 下面这里我用了数据集的绑定。用datareader也可以,这一段无关紧要。
     this.sqlDataAdapter1.SelectCommand.Parameters[0].Value = id;
     this.sqlDataAdapter1.Fill(this.db1);
      
     if (this.db1.DvdImg.Rows.Count == 0)
     {
         // 没有的话就转到一个事先准备的“没有图片”的地址上。
         this.Response.Redirect("images/noimg.jpg");
         return;
     }
     sExtFileName = this.db1.DvdImg[0].filetype;
     arImg = this.db1.DvdImg[0].Img;
      
     // 注意,下面要修改输出的mime格式,不然浏览器是不知道这是什么玩意儿的。
     // 不全,也就是个大概齐,大家可以加补充。
     string sMimeType;
     switch (sExtFileName)
     {
         case "jpg":
             sMimeType = "jpeg";
             break;
         case "bmp":
             sMimeType = "bitmap";
             break;
         case "gif":
             sMimeType = "gif";
             break;
         case "tif":
             sMimeType = "tiff";
             break;
         default:
             sMimeType = "jpeg";
             break;
     }
     Response.ContentType="image/" + sMimeType;
      
     // 写字节流到浏览器。
     Response.BinaryWrite(arImg);
  
     this.db1.Dispose();
}
  

Hmm, 好了. 现在已经可以动态地生成图像流了, 没有临时文件, 一切干干净净

阅读(4216) | 评论(0)


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

评论

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