代码改变世界

也从UpLoadFile说开去、

2010-03-12 10:09  北冥有魚,其名為坤、  阅读(486)  评论(0编辑  收藏  举报

近日不算很忙,闲暇之余研究了下,UploadFile控件,发现此控制种种弊端,特此写博提出这些弊端的解决方法.
其一,UploadFile控件与Updatepanel不兼容.
UploadFile1.PostedFile.FileName;取不到值.解决方法还算多吧,比如,Updatepanel设置个tirger让他回传啊(当然上传时就会刷新页面了).
要无刷新的话.可以另外建个页面.让后用frame连过来.这样每次刷新的就是另外一个页面,而本页看起来没有刷新过(这是欺骗客户眼睛的做法).
再说一种吧.那就是UploadFile以外你再在页面上弄个Html中的input,type="file".把file隐藏.当uploadFile选择改变时写javascript触发file的
选择的事件,再在后台取file的值.思路大概就有这么几种,大同小异,网路上也有很多相同的资料,我这里就不啰嗦了.

其二,UploadFile控件预览图片功能在IE6.IE7中不能显示图片.
这是个讨厌的问题,如果你是用jquery,那你不需要去研究这么多,不过你要是做外包.而客户规定不许用jquery,那你就活该受罪,烦啊.不过我这里
提供解决方案,经过本人测试.ok.绝对不会有什么问题.
页面代码部分:

代码
 <td rowspan="2">   
         
<img id="img1" height="120px" width="120px"  style="display:none;"/>     
         
<asp:Image ID="img" runat="server" height="120px" width="120px" />
  
</td>
 
<td colspan="2">
         
<asp:FileUpload ID="PicSmall" runat="server" onkeydown="event.returnValue=false;" onpaste="return false"
                 onchange
="javascript:setImagePreview( this.value );"  CssClass="btn"/><br />
         
<asp:Button ID="btnSmall" runat="server" Text="上傳至資料庫"  CssClass="btn" OnClick="btnSmall_Click"/>
 
</td>

用了2个图片控件一个是用来预览。另外一个是用来加载页面时读出数据库里存储的二进制图片数据并显示的。这里下面会说明。以下是javascript
代码,控制2个img的显示与隐藏,并在IE6中可以实现预览:

代码
<script language="javascript" type="text/javascript">
   
function setImagePreview( fileUrl ) 
        {        
             document.getElementById(
"ctl00_cphMain_UploadImg_img").style.display="none";
            
// document.getElementById("UploadImg1_img").style.display="none";
             
             document.getElementById(
"img1").style.display="block";
             
              
var i = fileUrl.lastIndexOf('.');        //从右边开始找第一个'.'
              var len = fileUrl.length;                //取得总长度
              var str = fileUrl.substring(len,i+1);    //取得后缀名
              var exName = "JPG,GIF,PNF,BMP,JPEG";               //允许的后缀名
              var k = exName.indexOf(str.toUpperCase());//转成大写后判断
             
             
if (window.navigator.userAgent.indexOf("MSIE")>=1)
              {    
                
if(k != -1)
                    {       
                        
var objDivFilter = document.getElementById("img1");             
                       
// var objDivFilter = document.getElementById("img")
                        if( fileUrl ) 
                        {    
                            objDivFilter.style.filter
="progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod = scale)";   //scale 是缩小图片到设置的大小,image是图片的原来大小
                            objDivFilter.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = fileUrl;   
                        } 
                    }
              }
              
else if(window.navigator.userAgent.indexOf("Firefox")>=1)
              {
                
              }   
           
        } 
</script>

 

这里判断了是否是图片,如果是的话就预览,先判断了IE,是IE就用滤镜,IE6中只有这种方式可以预览到图片,因为越高端的浏览器版本,禁用了越多的不安全
浏览方式.window.navigator.userAgent.indexOf("MSIE")>=1代表是IE.window.navigator.userAgent.indexOf("Firefox")>=1肯定是火狐咯,火狐
的浏览不难,到处能找到,我这里就不写明了.

其三,用Fileupload上传图片到数据库,又有麻烦.
如果你在本机操作的话,或者只限在服务器操作的话,那你还不会遇到这种问题.因为一般上传图片都会要求先判断图片大小或者长宽的,如何在后台获取预览图片的
长宽呢?System.Drawing.Image image = System.Drawing.Image.FromFile(url);???这样?还是?System.Drawing.Image image = System.Drawing.Image.inputStream()???这样?本人多次测试,发现FromFile这个方法自己是服务器端可以用,没有问题,可是如果是客户端选择了一张客户端
本机的图片,预览,上传的话,就会出问题了.因为服务器端根本没这张图片,图片是你客户端的,而FromFile这个方法需要传一个物理路径,等着报错吧.接着我又试了下
inputStream方法,诶.这个很好用,它是从内存流中把数据读取出来,并画图的.那就不会出现什么服务端没有这张图片这一说,不过用它的话,后面依然会出现大问题.
本人发现,用InputsTream判断长宽以后,再把图片存储到数据库,里面数据是有啦,不过都是些读取不出的没用数据,如0X0000000000000000000000,通过断点
得知每次走过InputsTream去画一次图,就改变了数据..迷茫.不过最后想到了办法,就用FromFile嘛,既然在服务器上没有错的话,在客户端操作的时候就把图片先上
传到服务器,再做相关操作,做完再删了不是就不会出现那种问题了么?以下是上传的代码.

代码
private void UpLoadIMG(FileUpload upImg)
        {
            
#region 上傳小圖
            Literal li 
= new Literal();
            
if (!upImg.HasFile)
            {
                li.Text 
= "<script>alert('請選擇一張圖片')</script>";
                
this.Page.Controls.Add(li);
                
return;
            }

            
string imgPath = upImg.PostedFile.FileName;
            
string fileExtName = imgPath.Substring(imgPath.LastIndexOf("."+ 1);
            
if (fileExtName != "gif" && fileExtName != "jpg" && fileExtName != "bmp" && fileExtName != "png" && fileExtName != "jpeg")
            {
                li.Text 
= "<script>alert('请选择GIF|JPG|BMP|PNG|JPEG格式的图片')</script>";
                
this.Page.Controls.Add(li);
                
return;
            }

            
if (imgPath.Contains(@":"))
            {
                
int height = Convert.ToInt32(ConfigurationManager.AppSettings["PicSmallH"]);
                
int width = Convert.ToInt32(ConfigurationManager.AppSettings["PicSmallW"]);
                
int smallHeight = 0;
                
int smallWidth = 0;
                
string fullpath = Server.MapPath("~/images/download/news/");//文件保存的路徑
                string path = Server.MapPath("images/download/news/" + imgPath.Substring(imgPath.LastIndexOf("\\"+ 1));
                
#region 判斷上傳文件是否存在,若不存在,則創建
                
if (!Directory.Exists(fullpath))
                {
                    
//創建文件夾
                    Directory.CreateDirectory(fullpath);
                    upImg.SaveAs(fullpath 
+ imgPath.Substring(imgPath.LastIndexOf("\\"+ 1));
                }
                
else
                {
                    upImg.SaveAs(fullpath 
+ imgPath.Substring(imgPath.LastIndexOf("\\"+ 1));
                }
                
#endregion
                
using (System.Drawing.Image image = System.Drawing.Image.FromFile(fullpath + imgPath.Substring(imgPath.LastIndexOf("\\"+ 1)))
                {
                    smallHeight 
= image.Height;
                    smallWidth 
= image.Width;
                }

                
if (fileExtName != "gif" && fileExtName != "jpg" && fileExtName != "bmp" && fileExtName != "png" && fileExtName != "jpeg")
                {
                    li.Text 
= "<script>alert('请选择GIF|JPG|BMP|PNG|JPEG格式的图片')</script>";
                    
this.Page.Controls.Add(li);
                }
                
else if (smallHeight != height || smallWidth != width)
                {
                    
// 縮略圖
                    
//定義變量
                    System.Drawing.Image.GetThumbnailImageAbort callb = null;
                    System.Drawing.Image imageSmall, imageBig;
                    
//加載大圖片
                    imageBig = System.Drawing.Image.FromFile(fullpath + imgPath.Substring(imgPath.LastIndexOf("\\"+ 1));
                    
//開始生成
                    imageSmall = imageBig.GetThumbnailImage(width, height, callb, new System.IntPtr());
                    
//獲取當前服務器時間
                    string time = DateTime.Now.ToString("yyyyMMdd"+ DateTime.Now.ToString("hhmmss");
                    
//保存縮略圖
                    imageSmall.Save(fullpath + time + imgPath.Substring(imgPath.LastIndexOf("\\"+ 1));
                    
string totalPath = fullpath + time + imgPath.Substring(imgPath.LastIndexOf("\\"+ 1);
                    
//儲存圖片
                    if (new Functions().UpLoadFile(totalPath, BARCODE, "PicSmall"))
                    {
                        
//ScriptManager.RegisterStartupScript(Page, GetType(), "", "alert('上傳成功')", true);
                        li.Text = "<script>alert('上傳成功')</script>";
                        
this.Page.Controls.Add(li);
                    }
                    
else
                    {
                        
// ScriptManager.RegisterStartupScript(Page, GetType(), "", "alert('上傳失敗')", true);
                        li.Text = "<script>alert('上傳失敗')</script>";
                        
this.Page.Controls.Add(li);
                    }

                    
//釋放圖片對象資源
                    imageSmall.Dispose();
                    imageBig.Dispose();

                    
//刪除圖片
                    System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath("~/images/download/news/" + time + imgPath.Substring(imgPath.LastIndexOf("\\"+ 1)));
                    img.ImageUrl 
= "/Modules/Web/Picture.aspx?image=" + BARCODE;
                    
                }
              
//刪除圖片
                System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath("~/images/download/news/" + imgPath.Substring(imgPath.LastIndexOf("\\"+ 1)));
            }

/// <summary>
        
/// 根據控件上傳圖片
        
/// </summary>
        
/// <param name="file">上傳控件</param>
        
/// <param name="barcode">編號</param>
        
/// <param name="size">大圖or小圖</param>
        
/// <returns>是否成功</returns>
        public bool UpLoadFile(FileUpload file, string barcode, string size)
        {
            
bool flag = false;
            
string strsql = string.Empty;
            
if (size.Equals("PicSmall"))
                strsql 
= "update product set PicSmall=@Pic where barcode = '" + barcode + "'";
            
else
                strsql 
= "update product set PicBig=@Pic where barcode = '" + barcode + "'";

            
string strConn = System.Configuration.ConfigurationManager.ConnectionStrings["Release"].ConnectionString;
            SqlConnection conn 
= new SqlConnection(strConn);
            
try
            {
                SqlCommand cmd 
= new SqlCommand(strsql, conn);
                
byte[] imagebyte = new byte[file.PostedFile.InputStream.Length];
                file.PostedFile.InputStream.Read(imagebyte, 
0, imagebyte.Length);

                cmd.Parameters.Add(
"@Pic", SqlDbType.Image).Value = imagebyte;
                conn.Open();
                cmd.ExecuteNonQuery();
                flag 
= true;
            }
            
catch (Exception ex) { Common.WriteLog("Functions.UpLoadFile", ex); }
            
finally
            {
                
if (conn.State == ConnectionState.Open)
                    conn.Close();
            }
            
return flag;
        }

        
/// <summary>
        
/// 根據路徑上傳圖片
        
/// </summary>
        
/// <param name="file">上傳路徑</param>
        
/// <param name="barcode">編號</param>
        
/// <param name="size">大圖or小圖</param>
        
/// <returns>是否成功</returns>
        public bool UpLoadFile(string photopath, string barcode, string size)
        {
            FileStream file 
= new FileStream(photopath, FileMode.Open, FileAccess.Read);
            Byte[] bytBLOBData 
= new Byte[file.Length];
            file.Read(bytBLOBData, 
0, bytBLOBData.Length);
            file.Close();

            
bool flag = false;
            
string strsql = string.Empty;
            
if (size.Equals("PicSmall"))
                strsql 
= "update product set PicSmall=@Pic where barcode = '" + barcode + "'";
            
else
                strsql 
= "update product set PicBig=@Pic where barcode = '" + barcode + "'";

            
string strConn = System.Configuration.ConfigurationManager.ConnectionStrings["Release"].ConnectionString;
            SqlConnection conn 
= new SqlConnection(strConn);

            
try
            {
                SqlCommand cmd 
= new SqlCommand(strsql, conn);

                cmd.Parameters.Add(
"@Pic", SqlDbType.Image).Value = bytBLOBData;
                conn.Open();
                cmd.ExecuteNonQuery();
                flag 
= true;
            }
            
catch (Exception ex) { Common.WriteLog("Functions.UpLoadFile", ex); }
            
finally
            {
                
if (conn.State == ConnectionState.Open)
                    conn.Close();
            }
            
return flag;
        }

 

此功能可预览,上传图片,改变图片长段,缩略显示.所有以上所述问题,基本解决,以下再附个从数据库读取二进制流并解析到页面图片显示的方法:

新建个页面在PageLoad事件里读出数据流,并写流.

代码
protected void Page_Load(object sender, EventArgs e)
        {
            DataSetProduct dsProduct 
= new ProductDal().GetProductPic(Request["image"]);
            
byte[] myData = new byte[0];
            
if (dsProduct.Product.Count > 0)
            {
                
if (Request.QueryString["type"!= "1"//小图
                {
                    
if (dsProduct.Tables[0].Rows[0]["PicSmall"].ToString() != "")
                        myData 
= (byte[])dsProduct.Tables[0].Rows[0]["PicSmall"];
                }
                
else//大图
                {
                    
if (dsProduct.Tables[0].Rows[0]["PicBig"].ToString() != "")
                        myData 
= (byte[])dsProduct.Tables[0].Rows[0]["PicBig"];
                }
            }
            Response.ContentType 
= "image/jpg";
            
if (myData.Length > 0)
                Response.OutputStream.Write(myData, 
0, myData.Length);
              
//Response.BinaryWrite(myData);

            Response.End();
        }

 

完事后把上面那个要显示的img的路径指到以上页面就可.img.ImageUrl = "/Picture.aspx";

好了,说了这么多,就到这吧.