在Web应用程序中上传文件时显示进度条

在开发Web应用程序时,经常需要为用户提供一个直观的反馈,尤其是在处理耗时较长的操作,如文件上传时。本文将介绍如何在ASP.NET2.0和.NET Framework2.0中创建一个显示上传进度的进度条。这个进度条会随着文件上传的进度实时更新,而不会触发页面回传。

最初,尝试在服务器端计算进度,并使用JavaScript定时器函数通过XMLHttpRequest对象从客户端更新进度条。但这种方法效果不佳,因为进度条要么显示0%,要么直接跳到100%,无法显示连续的进度。通过使用Mozilla Firebug追踪XMLHttpRequest对象的请求模式,发现XMLHttpRequest请求会在服务器端事件处理程序完成执行(即上传操作)后排队。因此,要么在服务器端上传开始之前就触发请求,要么在上传完成后触发,导致进度条无法正确显示进度。

感谢

在此,要感谢Munur Shaik先生提供的创意,在此基础上创建了进度条。同时,也要感谢架构师Anil Sistla对支持,帮助完成了解决方案。希望这篇文章能为那些寻找类似解决方案的人节省大量时间。

使用代码

下面展示了源代码结构。UploadProgressBar.ascx文件是一个用户控件,显示单个文件上传控件以及添加/移除按钮。添加按钮用于添加多个文件上传控件,而移除按钮则逐个清除文件上传控件。

FileUploadIframe.aspx包含一个简单的HTML IFrame标签,用于加载控件页面(FileUpload.aspx)。在这里,使用IFrame的原因是,放置多文件上传的主页面在按下上传按钮时不应该回传。

以下是创建进度条的代码:

public void CreateProgress(HttpFileCollection fileCollection) { StringBuilder sbProgress = new StringBuilder(); sbProgress.Append("<html><head><LINK REL=StyleSheet HREF='StyleSheet1.css' TYPE='text/css' /></head> <body>"); sbProgress.Append("<script src='JScript1.js' type='text/javascript'></script><table id='mainTable' border='1'>"); for (int i = 0; i < fileCollection.Count; i++) { string strProgressBarId = "progressBar" + i; string strPercentageId = "percentage" + i; string fileName = fileCollection[i].FileName; sbProgress.Append("<tr><td><p>" + fileName + "</p></td><td><div id='xxx' style='background-color:White; width: 100px;height:15px; border-color:Black;border-width:thin;border-style:solid'>"); sbProgress.Append("<div class='progressBar' id='" + strProgressBarId + "' ></div></div></td>"); sbProgress.Append("<td><p><div id='" + strPercentageId + "'></div></p></td></tr>"); } sbProgress.Append("</table>"); for (int i = 0; i < fileCollection.Count; i++) { sbProgress.Append("<script type='text/javascript'> SetProgressBarProgressAmount(" + i + ",0 );</script>"); } sbProgress.Append(PrepareTheGridHtml()); sbProgress.Append("</body><html>"); HttpContext.Current.Response.Write(sbProgress.ToString()); HttpContext.Current.Response.Flush(); }

上述CreateProgress()方法基本上将进度条HTML输出到输出流中,以创建一个空的进度条。在上面的代码中,SetProgressBarProgressAmount()是一个JavaScript方法,它接受两个参数:第一个参数是进度条的ID,这是在显示多个进度条时必需的;第二个参数是进度量。随着文件下载到服务器,这个进度条将根据下载的百分比设置,最后,当文件下载完成时,它将被设置为100%。在多文件上传的情况下,将显示多个进度条,每个文件一个,文件将一个接一个地上传到服务器,可以看到每个文件的进度量。

以下是将文件下载到服务器的代码:

public void DownloadTheFileToServer(HttpPostedFile file, int id) { Stream stream = null; FileStream fs = null; #region File Download Code goes here try { string strFileName = System.IO.Path.GetFileName(file.FileName); int contentLength = file.ContentLength; stream = file.InputStream; long totalUploadSize = stream.Length; int bufferSize = 0; if (totalUploadSize <= 1024) { bufferSize = 1024; } else if (bufferSize <= 4096) { bufferSize = 4096; } else if (bufferSize <= 8192) { bufferSize = 8192; } else { bufferSize = 16384; } byte[] b = new byte[1024]; int tripDownloadSize = 0; long totalDownloadedSize = 0; float Percentage = 0; bool isNewFile = true; string fileStoreLocation = ConfigurationManager.AppSettings["FileStoreLocation"]; fs = new FileStream(fileStoreLocation + strFileName, FileMode.Append); while ((tripDownloadSize = stream.Read(b, 0, 1024)) > 0) { fs.Write(b, 0, tripDownloadSize); totalDownloadedSize += tripDownloadSize; Percentage = (int)(totalDownloadedSize * 100) / totalUploadSize; setProgressBar(id, Percentage.ToString()); System.Threading.Thread.Sleep(100); isNewFile = false; } } catch (Exception objException) { throw objException; } finally { if (stream != null) { stream.Close(); stream.Dispose(); } if (fs != null) { fs.Close(); fs.Dispose(); } } }

在上述方法中,根据文件大小,编写了逻辑来决定流的缓冲区大小,但开发者可以根据自己的需求设置缓冲区大小(字节数组大小)。本文主要关注如何在文件下载过程中创建/更新进度。在上述代码中,在while循环内,每次计算总下载大小,并使用公式:总下载大小 / 总文件大小 * 100来确定下载的百分比。使用setProgressBar(id, Percentage)方法,可以为特定ID的进度条设置进度。

设置进度条

以下是SetProgressBar方法的代码:

public static void setProgressBar(int id, string progressAmount) { StringBuilder sb = new StringBuilder(); sb.Append("<body><script type='text/javascript'>SetProgressBarProgressAmount(" + id + ",'" + progressAmount + "'); </script></body>"); HttpContext.Current.Response.Write(sb.ToString()); HttpContext.Current.Response.Flush(); }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485