关于图片的存与读
场合:
在一个详细信息页面中,至少包含一个file控件和一个img控件。在新增时,用file加载一张本地图片,在img里显示,然后保存,将图片存入Oracle表中的Blob字段里;在读取时,读取Blob字段,将图片直接写入img控件,若图片大小过大,则对图片进行压缩。
页面部分代码:
<div align="center" id="div1" runat="server" style="width: 120px; height: 150px;"> <asp:Image ID="img_ZP" runat="server" Style="width: 120px; height: 150px;" /> </div> <input id="file_PMT" style="width: 220px" onpropertychange="DoShowPicture(this.value,'img_ZP');" type="file" name="file_PMT" runat="server">
点击file,在img中显示图片的js:
1 //显示图片 2 function DoShowPicture(vPicPath, imgName) { 3 var img; 4 5 if (vPicPath.length < 1) { 6 return false; 7 } 8 img = document.getElementById(imgName); 9 try { 10 setTimeout(function() { img.src = vPicPath }, 20); 11 } 12 catch (e) { 13 } 14 }
图片读入时的验证:
$(function(){ $("#img_ZP").on("load",function(){ CheckZJZImg(this); }).error(function(){ alert("请选择一个图像文件!"); //清除file内容(使用替换的方法) var file = $("#file_PMT") ; file.after(file.clone().val("")); file.remove(); }); });
验证方法:
1 //检测图片 2 function CheckZJZImg(img) { 3 var file = $("#file_PMT") ; 4 if (img.fileSize > (1024 * 100)) { 5 alert("您选择的图片大小为:" + img.fileSize + "\n注意:大小不能超过100K,请重新选择!"); 6 file.after(file.clone().val("")); 7 file.remove(); 8 img.src = ''; 9 return false; 10 } 11 if (img.width > 358 || img.height > 441) { 12 alert("您选择的图片宽为:" + img.width + ",高为:" + img.height + "\n注意:尺寸大小不能超过358(宽)X441(高),请重新选择!"); 13 file.after(file.clone().val("")); 14 file.remove(); 15 img.src = ''; 16 return false; 17 } 18 return true; 19 }
验证完毕,就可以保存了,下面是保存方法:
1 string filename = file_PMT.PostedFile.FileName; 2 if (filename != "" && "jpg,bmp,png,jpeg,gif".Contains(filename.Substring(filename.LastIndexOf('.') + 1).ToLower())) 3 { 4 int PMTLength = file_PMT.PostedFile.ContentLength; 5 byte[] PMTContent = new byte[PMTLength]; 6 file_PMT.PostedFile.InputStream.Read(PMTContent, 0, PMTLength); 7 info.ZP = PMTContent; 8 } 9 else 10 { 11 info.ZP = new byte[0]; 12 } 13 //然后把info.ZP传到保存方法里即可
此处会用到二进制流转化为大对象的方法:
1 /// <summary> 2 /// 取得ORACLEBLOB对象 3 /// </summary> 4 /// <param name="p_ByteObject">二进制字节数组对象</param> 5 /// <returns></returns> 6 protected OracleLob GetOracleBlob( byte[] p_ByteObject ) 7 { 8 OracleLob tempLob; 9 string cmdText; 10 11 try 12 { 13 cmdText = "DECLARE xx blob; BEGIN DBMS_LOB.CREATETEMPORARY"; 14 cmdText += "(xx, false, 0); :tempBlob := xx; END;"; 15 16 m_Connection.Open(); 17 18 OracleTransaction tx = m_Connection.BeginTransaction(); 19 OracleCommand oracleCommand = m_Connection.CreateCommand(); 20 oracleCommand.Transaction = tx; 21 22 oracleCommand.CommandText = cmdText; 23 oracleCommand.Parameters.Add(new OracleParameter("tempBlob", OracleType.Blob)).Direction = ParameterDirection.Output; 24 25 oracleCommand.ExecuteNonQuery(); 26 27 tempLob = (OracleLob)oracleCommand.Parameters[0].Value; 28 29 tempLob.BeginBatch(OracleLobOpenMode.ReadWrite); 30 tempLob.Write(p_ByteObject,0,p_ByteObject.Length); 31 tempLob.EndBatch(); 32 33 tx.Commit(); 34 } 35 catch(Exception exp) 36 { 37 throw new AppException(exp.Message, exp); 38 } 39 finally 40 { 41 m_Connection.Close(); 42 } 43 44 return tempLob; 45 }
至此,保存完毕。
下面是读取
首先,在读取之前,清空创建的缓存文件夹。因为下面用到的读取方法会在服务器端生成图片,然后将该图片的地址赋给页面的img。所以,如果不清理的话,会使服务器端的图片越来越多。
“../SellerManage/CacheImage/” 这个路径是手动在服务器端创建的
1 /// <summary> 2 /// 清理缓存图片 3 /// </summary> 4 private void ClearCacheImage() 5 { 6 //获取缓存图片文件夹路径 7 string cacheDocument = Server.MapPath("../SellerManage/CacheImage/"); 8 //若没有,则创建 9 if (!System.IO.Directory.Exists(cacheDocument)) 10 { 11 System.IO.Directory.CreateDirectory(cacheDocument); 12 } 13 else 14 { 15 // Search the directory 16 DirectoryInfo di = new DirectoryInfo(cacheDocument); 17 //FileInfo[] f = di.GetFiles("*.xls");//文件夹下的.xls文件 18 FileInfo[] f = di.GetFiles();//文件夹下所有文件 19 foreach(FileInfo myFile in f) 20 { 21 myFile.Delete(); 22 } 23 } 24 }
读取图片:info.ZP是byte[]类型
1 /// <summary> 2 /// 读取图片 3 /// </summary> 4 private void DoLoadData() 5 { 6 ClearCacheImage(); //先清理缓存图片 7 if (Request.QueryString["rybh"] != null) 8 { 9 this.hidn_rybh.Value = Request.QueryString["rybh"].ToString(); 10 } 11 string is_rybh = this.hidn_rybh.Value; 12 SellerInfo info = SellerBAL.GetSellerInfo(is_rybh); 13 14 if (info.ZP != null && info.ZP.Length != 0) 15 { 16 MemoryStream stmImageCol = new MemoryStream(info.ZP); 17 System.Drawing.Image img = System.Drawing.Image.FromStream(stmImageCol); 18 System.Drawing.Bitmap image = new System.Drawing.Bitmap(img); 19 string imgname = DateTime.Now.ToString("yyyyMMddhhmmss") + ".jpg"; 20 string path = "../SellerManage/CacheImage/" + imgname; 21 image.Save(Server.MapPath(path)); 22 //压缩图片 23 CompressImage(Server.MapPath(path), image, 0); 24 this.img_ZP.ImageUrl = path; 25 } 26 }
压缩图片,是为了使我们读出的图片符合显示规则(例如图片文件大小、质量等等)
1 /// <summary> 2 /// 压缩图片 3 /// </summary> 4 /// <param name="path">已生产的图片地址</param> 5 /// <param name="orIMG">从数据库中读取的原图</param> 6 /// <param name="flag">标识</param> 7 private void CompressImage(string path, System.Drawing.Bitmap orIMG, int flag) 8 { 9 int imgSize = flag == 0 ? 100 : 300; //0:头像 1:身份证扫描件 单位KB 10 11 FileInfo f = new FileInfo(path); 12 if (f.Length > 1024 * imgSize) 13 { 14 ImageCodecInfo CodecInfo = GetImageCodecInfo(ImageFormat.Jpeg); 15 System.Drawing.Imaging.EncoderParameters encoderParams = new System.Drawing.Imaging.EncoderParameters(1); 16 encoderParams.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 2); 17 orIMG.Save(path, CodecInfo, encoderParams); 18 encoderParams.Dispose(); 19 } 20 } 21 22 private ImageCodecInfo GetImageCodecInfo(ImageFormat format) 23 { 24 ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); 25 ImageCodecInfo CodecInfo = null; 26 foreach (ImageCodecInfo item in codecs) 27 { 28 if (item.FormatID == format.Guid) 29 { 30 CodecInfo = item; 31 break; 32 } 33 } 34 return CodecInfo; 35 }
至此,图片显示完毕,在img中显示的是压缩后的图片,js校验的也是压缩后的图片大小。
这种读取方式可以用于预览,数据库只保存一张原图,不用保存多张图片。但仅用于单人操作,多人同时操作会删除缓存图片,造成无法读图。此代码有待改进。
浙公网安备 33010602011771号