需求是: 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, 好了. 现在已经可以动态地生成图像流了, 没有临时文件, 一切干干净净

评论