C#中使用FileUpload上传图片到SQL数据库中以image类型存储并使用Image控件显示注意事项

当我们需要以数据流存储图片到数据库中而不是文件路径),需要考虑很多因素,不同的环境决定了采取不同方法。

1.将图片存入数据库。首先,当我们决定使用FileUpload上传图片,需要考虑,FileUpload的功能主要是在客户端选取图片,然后使用FileUpload的SaveAs方法将选取的图片的地址保存到服务器端保存,因为我们使用的数据流存储图片,所以没有必要将图片保存到服务器端。

其次,FileUpload没有像OpenDialog的.Filter方法过滤图片的格式,即实现打开对话框,只能选择图片格式的文件的形式。所以这里我们需要自己写代码过滤文件的格式。


下面就是上传图片的主要代码:

//上传图片
if(fupContractPhoto.PostedFile.ContentLength<500000)//限制文件大小为100000为100K
{
           string fileFullName = this.fupContractPhoto.PostedFile.FileName;  //文件完整名称
           string fileName = fileFullName.Substring(fileFullName.LastIndexOf("\\") + 1);   //文件名
           string type = fileName.Substring(fileName.LastIndexOf(".") + 1);    //文件类型
           if (type.ToLower() == "bmp" || type.ToLower() == "jpg" || type.ToLower() == "gif" || type.ToLower() == "png")
           {
                        string fileFullPath=Server.MapPath("~/upload")+"\\"+fileName;
                        this.fupContractPhoto.SaveAs(fileFullPath);

                        //将文件转化为数据流
                        FileStream fs = new FileStream(fileFullPath, FileMode.Open);    //文件流
                        byte[] imageBytes=new byte[fs.Length];  //设定字节流数组大小
                        BinaryReader br = new BinaryReader(fs);     //读字节对象
                        imageBytes = br.ReadBytes(Convert.ToInt32(fs.Length));  //将字节流读入字节数组中
                        
                        //将字节流对象赋值给Project对象
                        project.ContractPhoto = imageBytes;

            }

}

需要说明的是:Asp.net代码页面里使用的是对象类型的某个字段存储图片转化成的Byte[ ]字节数组,这里使用的Project对象的一个实例project的属性ContractPhoto。数据库中使用的是Image类型的字段存储将要上传的图片。

下面就是和数据库交互的语句:

首先因为这里将图片转换成字节流并用字节数组存储,有人会想直接使用insert语句插入到数据中对应的字段可不可以,答案是不可以的。如这样的形式:string sql=string.Format("insert into Project(ContractPhoto) values('{0}')",project.ContractPhoto);通过断点调试可以看到存入数据库中的是System.Drawing而不是字节流数据。那么我们通过Convert.toBase64String将字节流转化成二进制字符串可以吗?答案是可以的,但是当显示图片会出现无法显示的情况。那么我们如何将数据插入到数据库中呢?这个问题纠结了很长时间,最后通过Command类将需要插入数据库中的数据以参数的形式插入到数据库,这种方法是可行的。如这样的形式:string sql="insert into Project(ContractPhoto) values(@ContractPhoto)";然后使用SqlParameter类组织参数数组。由于SQLHelper类是微软编写的Ado.net类用户数据库交互提供方便这里就简洁点通过这个类来具体实现。

下面就是实现插入自己数组数据到数据库中的代码:

 public int AuditProject(Project project)
{
            //SQL语句
            string sql = "update Project set ProjectStatus=2,ContractNO=@ContractNO,ContractAmount=@ContractAmount,ContractPhoto=@ContractPhoto where ProjectID=@ProjectID";
            //组织参数


            SqlParameter[ ] objParams = new SqlParameter[4];
            objParams[0] = new SqlParameter("@ContractNO",project.ContractNO);  //合同编号
            objParams[1] = new SqlParameter("@ContractAmount", project.ContractAmount); //合同金额
            objParams[2] = new SqlParameter("@ContractPhoto", project.ContractPhoto);   //合同照片
            objParams[3] = new SqlParameter("@ProjectID", project.ProjectID);   //项目编号


            return SqlHelper.ExecuteNonQuery(SqlHelper.ConnString, CommandType.Text, sql, objParams);
        }

这里使用的是我的项目中部分代码用户展示,可以借鉴其中的方法实现具体功能。主要加了一个参数类,通过参数传入,最后通过Cammand类实现的(因为SQLHELPER类已经封装,这里看不到具体实现)。

2.下面就是数据库中图片显示到Asp.net页面中。首先我们需要考虑使用什么控件显示,并注意控件的特性。一般使用Image服务器控件显示图片,问题来了如何显示呢。因为Image控件使用的是给Image的ImageURL属性赋图片路径值显示,而我们存储图片是以二进制字节流形式存储图片而不是图片的路径。我们只能通过其他形式转化来。具体实现:在我们的页面添加一个ContractPhoto.aspx(名字可以随便写),这个页面主要实现功能的不用于显示图片的,主要利用Response的一个读二进制字节流的方法,然后将将图片显示在Image控件中的形式。具体做法:<asp:Image ID="imgContractPhoto" runat="server" Height="360px" Width="721px" />

在服务器后台代码中这样写: 

imgContractPhoto.ImageUrl = "ContractPhoto.aspx?ProjectID=" + project.ProjectID; //图片

用于指向图片页面并传递相应参数用于一个控件在不同条件下显示不同图片的功能。

下面就是ContractPhoto.aspx后台代码的实现:

 protected void Page_Load(object sender, EventArgs e)
        {
            //定义ProjectID获取QueryString中获取的ProjectID
            int projectID = Convert.ToInt32(Request.QueryString["ProjectID"]);
            //通过projectID获取Project信息
            Project project = projectManager.GetProjectByProjectID(projectID);
            byte[ ] b_ContractPhotoImg =project.ContractPhoto;
            if (b_ContractPhotoImg.Length > 0)
      {
    Response.Clear();
    Response.ContentType = "image/jpeg";
               Response.OutputStream.Write(b_ContractPhotoImg, 0, b_ContractPhotoImg.Length);
    Response.End();
      }
        }

由于数据中取出数据给project.ContractPhoto的过程被我省略了,这里贴一个短小代码显示取字节流的过程。

 project.ContractPhoto = (byte[ ])(reader["ContractPhoto"]);    //合同图片

reader是SqlDataAdapter对象。

这样就可以显示数据库中存储的字节流数据了。

3.还有个很重要的问题需要交代:大家都以为只要我们的程序发布到IIS上就可以实现功能了,确实是这样的在本地IIS上发布网页,实现功能没有任何问题,但是发布到远端的服务器上就会提示文件没有权限或者文件地址不存在问题。这个问题纠结了很长时间终于解决了。问题的根源主要有两个:1.本地的文件上传到服务器上,我们使用FileUpload上传时,会显示文件地址,但这个地址是我们本地文件中的地址,当我们把网页发布到服器上的IIS时,服务器却找不到本地计算机所存地址,就会提示文件不存在问题。如果是本地,并在本地发布IIS本地的IIS能直接访问本地路径,当然没有任何问题。问题来,怎样实现功能呢???2.我们可以“曲线救国”,直接存不行,我们可以使用FileUpload的SaveAs方法 先在服务上建立一个upload文件夹,然后使用SaveAs方法将本地的文件存放到upload文件夹里。当我们需要访问文件时直接使用Server.Mappath方法获取项目所在地址并找到upload中文件。如果使用完不需要可以使用File.Delete(string path)方法删除服务器端文件。这么说有点抽象贴一段代码就很明显了。

代码如下:

    string fileFullPath=Server.MapPath("~/upload")+"\\"+fileName;
this.fupContractPhoto.SaveAs(fileFullPath);
//将文件转化为数据流
FileStream fs = new FileStream(fileFullPath, FileMode.Open);    //文件流
byte[] imageBytes=new byte[fs.Length];  //设定字节流数组大小
BinaryReader br = new BinaryReader(fs);     //读字节对象
imageBytes = br.ReadBytes(Convert.ToInt32(fs.Length));  //将字节流读入字节数组中

至此所有的功能点都讲完了,大家可以根据自己的项目需要汲取其中一两点。因为看了网上讲的鱼龙混杂,所以在这完整的表述出来,希望能给大家帮助!

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值