文章教程

第26章文件批量上传系统

8/31/2020 9:10:17 PM 人评论 次浏览

第26章 文件批量上传系统

本章视频教学录像:14分钟

文件上传是开发项目中必不可少的功能,也是用户和网站管理者之间的交流工具。本章使用JavaScript介绍如何动态地添加上传文件。

本章要点(已掌握的在方框中打钩)

□ 了解批量上传的原理

□ 创建数据库和数据表

□ 设计系统前台页面

□ 设计批量上传代码

□ 将批量上传系统添加至已有网站中

26.1 系统分析

本节视频教学录像:2分钟

网站建成后,用户希望能够保存一些文件信息到网站上,系统管理员由于工作的需要,经常要上传很多图片文件到系统中,如果能够批量上传信息,则能更好地满足需要。

本章使用ASP.NET和SQL Server 2008来创建一个批量上传系统。

figure_0565_0914

26.1.1 系统目标

本系统需要实现的目标有以下4点。

⑴根据需要添加上传控件。

⑵根据需要删除上传控件。

⑶保存上传信息。

⑷显示上传信息。

26.1.2 系统原理

当用户需要上传文件时,单击【添加附件】按钮可以动态地增加上传控件,单击【删除】按钮可以移除多余的上传控件。用户选择好要上传的文件,单击【上传】按钮即可保存所有选定的文件信息到网站中。

26.1.3 技术要点

如何获取上传的文件个数呢?

当用户上传文件时,本系统通过Request的Files属性获得请求中的文件信息,然后根据获得的文件信息的个数逐个保存到网站中。如果用户未选择上传文件,那么得到的文件名肯定是空字符串,则不保存该条信息。代码将在26.3.4小节中介绍。

26.2 数据库分析及设计

本节视频教学录像:1分钟

根据分析,本系统需要用到数据库来存储上传文件保存的数据,所以在系统开发之前,首先要进行数据库的设计。

26.2.1 数据库分析

在批量上传系统中,需要保存用户上传的文件信息,包括文件名、保存的位置、保存的时间、文件的类型等信息。

26.2.2 创建数据库

在SQL Server 2008中创建数据库的具体步骤如下。

⑴选择【开始】figure_0566_0915【所有程序】figure_0566_0916【Microsoft SQL Server 2008】figure_0566_0917【SQL Server Management Studio】,以【SQLServer身份验证】模式登录。

figure_0566_0918

⑵在【对象资源管理器】窗口中的【数据库】节点上右击,在弹出的快捷菜单中选择【新建数据库】菜单项,弹出【新建数据库】对话框。

figure_0566_0919

⑶在【数据库名称】文本框中输入“ch26DataBase”,在【数据库文件】列表框中使用默认设置“ch26DataBase”和“ch26DataBase_log”文件的路径,然后单击【确定】按钮,即可完成ch26DataBase数据库的创建。

26.2.3 创建数据表

本实例中需要一张记录上传文件相关信息的表,下面来创建数据表。

⑴在【对象资源管理器】中展开ch26DataBase节点,右击【表】节点,在弹出的快捷菜单中选择【新建表】菜单项。

figure_0567_0920

⑵在打开的表编辑窗口中,按照下表进行输入。

figure_0567_0921

⑶在【dbo.Table_1*】选项卡上右击,在弹出的快捷菜单中选择【保存】菜单项,弹出【选择名称】对话框,在【输入表名称】文本框中输入“tabUploadFile”,然后单击【确定】按钮,即可完成表的创建。

26.3 系统设计

本节视频教学录像:6分钟

在26.1.1小节中,我们已经提出了批量上传系统需要实现的4个目标,所以在系统设计时,需要设计4个模块来实现各个目标。

26.3.1 系统页面设计

首先设计系统的页面,页面中需要有【添加附件】按钮、【上传】按钮,上传控件在单击【添加附件】按钮时显示。

⑴在Visual Studio 2010中,新建【语言】为【Visual C#】的ASP.NET空网站,添加一个默认的Default.aspx页面。

⑵在Default.aspx页面的设计视图中,如图所示设计系统界面,所用控件及属性设置如表所示。

figure_0567_0922
figure_0568_0923

⑶为了动态添加上传控件,需要使用JavaScript脚本来实现此功能。在源视图的<title>< /title>标签对之后添加脚本函数(代码26-1.txt)。

01 <script language="javascript" type="text/javascript">

02 function AddFileCtrol() {            //添加一个上传控件

03 var innerDiv=document.createElement("div");  //新建一个Div元素

04 document.getElementById("dv1").appendChild(innerDiv) //添加到Div元素中

05 var fileCtrol=document.createElement("input");  //建立 input元素

06 fileCtrol.name= "upFile";           //设置元素的名称

07 fileCtrol.type= "file";             //设置元素的类型

08  innerDiv.appendChild(fileCtrol);        //添加到 fileCtrol元素

09 var btnCtrol=document.createElement("input");  //建立 input元素

10 btnCtrol.name= "btnDelete";          //设置元素的名称

11 btnCtrol.type= "button";           //设置元素的类型

12 btnCtrol.setAttribute("value", "删除 ");      //设置元素的显示文字

13 btnCtrol.onclick= function() {DeleteFileCtrol(this.parentNode) };   //绑定删除上传控件函数到onclick事件

14  innerDiv.appendChild(btnCtrol);        //添加到Div元素

15 }

16 function DeleteFileCtrol(obj) {          //删除对应上传控件函数

17 document.getElementById("dv1").removeChild(obj);

18 }

19 < /script>

⑷在网站中添加1个名为“UserRegist.aspx”的Web页面,用于显示上传的文件信息以供下载。在UploadFileList.aspx页面的设计视图中,如图所示设计系统界面,所用控件及属性设置如表所示。

figure_0568_0924
figure_0569_0925

26.3.2 配置网站的Web.config

数据库和系统页面都设计好了,如何将它们连接起来呢?这就需要通过配置系统的Web.config文件来连接数据库。

在【解决方案资源管理器】中双击Web.config文件,打开Web.config的代码窗口,然后将<connectionStrings>和< /connectionStrings>之间的代码更换为以下代码。

<add name="ch26DataBase" connectionString="Data Source= localhost;Initial Catalog=ch26DataBase;User ID=sa;Password=123"/>

【代码详解】

此段代码的作用是添加一个数据库的连接字符串,“localhost”表示要连接当前本机的数据库,读者也可设定为数据库所在服务器的IP地址。数据库的名称为“ch26DataBase”。

26.3.3 数据库连接代码设计

在系统保存上传信息时要连接数据库,结束时要关闭此连接。所有的相关数据操作使用一个公共数据类来实现。

新建一个类文件,命名为“DataClass.cs”,添加GetSqlServerConn方法,用于获得数据库连接(代码26-2.txt)。

01 private SqlConnection GetSqlServerConn()

02 {

03 SqlConnection sqlConn;    //定义SQlServer连接对象

04 string strConn = WebConfigurationManager.ConnectionStrings["ch26DataBase"].ConnectionString; //读取Web.config配置文件的ConnectionString节点获取连接字符串

05 sqlConn= new SqlConnection(strConn);  //生成数据库连接对象

06 sqlConn.Open();    //打开数据库连接

07 return sqlConn;    //返回数据库连接对象以供调用

08 }

继续添加CloseSqlServerConn方法,用于关闭数据库连接(代码26-3.txt)。

01 private void CloseSqlServerConn(SqlConnection sqlConn)

02 {

03  if (sqlConn.State==ConnectionState.Open) //如果数据库连接处于关闭状态,则打开此连接

04 {

05 sqlConn.Close();

06 }

07 }

26.3.4 保存上传信息代码设计

有了数据库连接,我们就可以通过它保存上传文件的信息,系统可以将此信息保存至数据库。在公共类中继续添加SaveFilesInfo方法来保存上传文件的信息内容(代码26-4.txt)。

01 public bool SaveFilesInfo(HttpFileCollection fileColl)

02 {

03 SqlConnection sqlConn;

04 SqlCommand sqlComm;

05 string strComm=@"insert into

06    tabUploadFile(NewFileName,OldFileName,SaveAddress,UploadTime,TypeName)

07  values(@NewFileName,@OldFileName,@SaveAddress,@UploadTime,@ TypeName)";

08 sqlConn=GetSqlServerConn();      //调用方法获取数据库连接

09 SqlTransaction sqlTran= sqlConn.BeginTransaction(); //开始数据库事务

10 StringBuilder sbFileName;

11  try

12 {

13 sqlComm= new SqlCommand(strComm, sqlConn);

14 sqlComm.Transaction= sqlTran;   //指定命令要使用的事务

15  for (int i= 0; i< fileColl.Count; i++)   //循环保存上传信息

16  {

17    if (!String.IsNullOrEmpty(fileColl[i].FileName))

18   {

19  sbFileName= new StringBuilder();  //使用年月日时分秒毫秒生成文件名

20  sbFileName.Append(DateTime.Now.Year);

21  sbFileName.Append(DateTime.Now.Month);

22  sbFileName.Append(DateTime.Now.Day);

23  sbFileName.Append(DateTime.Now.Hour);

24  sbFileName.Append(DateTime.Now.Minute);

25  sbFileName.Append(DateTime.Now.Second);

26  sbFileName.Append(DateTime.Now.Millisecond);

27  sbFileName.Append(Path.GetExtension(fileColl[i].FileName));

28  sqlComm.Parameters.Clear(); //清空以前参数,指定当前SQL命令参数

29  sqlComm.Parameters.AddWithValue("@NewFileName", sbFileName.ToString());

30   sqlComm.Parameters.AddWithValue("@OldFileName", Path.GetFileName(fileColl[i].FileName));

31  sqlComm.Parameters.AddWithValue("@SaveAddress", System.Web.HttpContext.Current.Server.MapPath("~/Upload/"));

32  sqlComm.Parameters.AddWithValue("@UploadTime",DateTime.Now);

33   sqlComm.Parameters.AddWithValue("@TypeName", Path.GetExtension (fileColl[i].FileName));

34  sqlComm.ExecuteNonQuery();  //执行SQL命令

35     fileColl[i].SaveAs(System.Web.HttpContext.Current.Server.MapPath("~/Upload/") +sbFileName.ToString());     //保存对应的文件到服务器

36   }

37  }

38 sqlTran.Commit();     //提交事务保存数据

39  return true;

40 }

41 catch (Exception ex)

42 {

43 sqlTran.Rollback();     //发生异常回滚事务

44 CloseSqlServerConn(sqlConn);   //关闭数据库连接

45  return false;

46 }

47 }

26.3.5 获取上传文件信息代码设计

对用户上传的文件信息可以随时下载,因此需要将上传的文件信息显示给用户。在公共类中继续添加GetFilesInfo方法来获取上传文件的信息内容(代码26-5.txt)。

01 public DataTable GetFilesInfo()

02 {

03 SqlConnection sqlConn;

04 SqlDataAdapter sqlAdpt;

05 DataTable dtFilesInfo;

06 string strComm = "select NewFileName,OldFileName,SaveAddress,UploadTime,TypeName from tabUploadFile";

07  try

08 {

09 sqlConn=GetSqlServerConn();

10 sqlAdpt= new SqlDataAdapter(strComm, sqlConn); //使用数据适配器读取数据

11 dtFilesInfo= new DataTable();

12 sqlAdpt.Fill(dtFilesInfo);      //填充数据到DataTable

13  return dtFilesInfo;

14 }

15 catch (Exception ex)

16 {

17  throw ex;

18 }

19 }

26.3.6 保存上传文件的事件代码设计

用户选择好上传的文件之后,单击【上传】按钮可以保存文件信息。在Default.aspx设计页面双击“上传”按钮自动添加事件btnUpload_Click方法,添加以下代码(代码26-6.txt)。

01 protected void btnUpload_Click(object sender,EventArgs e)

02 {

03 HttpFileCollection fileColl=Request.Files;  //获取当前请求中所有的文件信息

04 DataClass dc= new DataClass();

05 bool bResult= false;     //判断保存是否成功

06  try

07 {

08 bResult=dc.SaveFilesInfo(fileColl);

09 }

10 catch (Exception ex) { }

11  if (bResult)

12 {

13 Response.Write("<script>alert('文件保存成功! ')< /script>");

14 }

15 else

16 {

17 Response.Write("<script>alert('文件保存失败! ')< /script>");

18 }

19 }

26.3.7 下载上传文件的事件代码设计

本系统将用户上传的文件信息显示在页面上,当单击对应信息的时候,可以下载该文件。在UploadFileList.aspx设计页面空白处双击添加Page_Load窗体事件,添加以下代码(代码26-7.txt)。

01 protected void Page_Load(object sender,EventArgs e)

02 {

03  if (!IsPostBack)  //第一次打开页面绑定文件信息到GridView控件

04 {

05  this.grdFileList.DataSource= new DataClass().GetFilesInfo(); //绑定文件信息数据

06  this.grdFileList.DataBind();

07 }

08 }

由于页面显示文件名的字段NavigateUrl属性使用了一个处理方法GetFileUrl生成保存在服务器端的文件名,所以需要继续添加GetFileUrl方法(代码26-8.txt)。

01 public string GetFileUrl(string strAddress, string strFileName)

02 {

03 return strAddress+ strFileName;  //获取服务器保存的文件实际路径和实际文件名

04 }

26.4 运行系统

本节视频教学录像:2分钟

下面来看系统运行的效果。

⑴按【F5】或【Ctrl+F5】快捷键,在浏览器中运行该程序,页面中将显示【添加附件】和【上传】按钮。

figure_0573_0926

⑵单击【添加附件】按钮,可自动生成一个上传控件和一个【删除】按钮。连续单击可生成多个上传控件,单击【删除】按钮可删除对应的上传控件。

figure_0574_0927

⑶单击【上传】按钮,将文件信息保存到数据库中并将文件保存至服务器,保存完成后返回提示信息,如图所示。

⑷用户可以访问UploadFileList.aspx页面查看上传的文件信息,如图所示。

figure_0574_0928

⑸用户单击对应的文件名或目标执行另存为操作可以下载该文件。

figure_0574_0929

26.5 在我的网站中应用本系统

本节视频教学录像:1分钟

将Default.aspx页面中相关的代码拷贝至一个已存在页面作为部分代码,或者将该页面改名后作为一个链接添加至已有页面中即可。其余相关代码文件无需改动,拷贝至已有网站对应的位置就可以运行。应该根据具体情况修改数据库表,可以在其中添加一个用户字段,以区分每个用户上传的文件信息。更多的细化功能读者可自行练习,这里不再赘述。

26.6 开发过程中的常见问题及解决方式

本节视频教学录像:2分钟

开发过程中应该注意以下几点。

⑴使用JavaScript脚本语言时,读者要熟练掌握使用脚本语言生成Html控件的方法,特别要注意脚本事件是如何绑定到对应按钮上的。

⑵保存上传文件的时候,一般情况下都要对文件进行改名保存,以防止重名文件的出现。常用的方法是取得当前系统时间加上毫秒级的时间组成新的文件名。

⑶在GridView显示数据的时候,我们会发现保存的文件路径和文件名称需要组合成一个字段显示,这时需要一个转换函数,即代码中提到的GetFileUrl (string strAddress, string strFileName)函数,此函数将两个字段信息组合后重新绑定到GridView控件上。需要注意的是此函数一定要是Public类型的,否则前端页面代码不能使用此函数。

⑷在GridView显示数据的时候,我们还会发现日期字段显示的时候会出现年月日时分秒的格式,为了去除多余的时间,需要格式化该字段,需要使用DataFormatString="{0:yyyy-MM-dd}",使日期只显示年月日的格式。但是需要注意的是,一定要把HtmlEncode属性设置为False,否则DataFormatString属性不起作用。

⑸在使用上传控件上传文件信息的时候,一定要注意在form 标签的属性中添加“enctype="multipart/form-data"”代码,否则使用Request的Files属性将获取不到请求中的文件信息。

⑹当同时上传多个文件的时候,要注意事务的使用,以确保多个文件同时上传成功。否则用户不知道哪些文件上传成功,哪些失败,将造成使用上的不便。

教程类别