65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Flash 和 ASP.NET 进行多文件上传并带进度条

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (283投票s)

2006 年 9 月 28 日

CPOL

6分钟阅读

viewsIcon

5755317

downloadIcon

42920

如何在中等信任托管环境中 Flash 上传多个文件

引言

很难找到一个合适的上传控件,该控件能够处理大文件、显示进度条,并且在中等信任的托管环境中也能正常工作。这些控件的问题在于,中等信任不允许使用反射。但这并不意味着我们束手无策。这些控件试图解决的一个问题是,当大文件通过流式传输到磁盘时,服务器可能会耗尽内存。但是,HttpPostedFile 类的描述指出,“默认情况下,所有大于 256 KB 的请求(包括表单字段和上传的文件)都会被缓冲到磁盘,而不是保留在服务器内存中。”因此,我们不必担心这个问题。另一个问题是通过进度条向用户提供反馈。这时就需要 Flash 的 fileReference API,它允许你从 Flash 上传文件,并跟踪它。FileReferenceList 允许用户选择多个文件。

Using the Code

在论坛提问之前,请先阅读文章和源代码中的注释。

我终于有时间更新这篇文章的 Flash 部分了。我使用 Flex 重写了它,并尝试添加了一些来自留言板的建议。一些新功能包括:添加文件时不会清除之前添加的文件、移除单个文件、显示单个文件进度条以及总进度条、取消上传后不会重新上传已上传的文件、在上传文件时可以添加和移除文件。代码是用代码隐藏编写的,应该更容易修改。此外,你只需要一个文本编辑器就可以编译它,并且可以使用 Adobe 提供的免费下载的 Flex 2 SDK 进行编译。错误处理应该也得到了改进,但可能需要添加更多代码来更好地处理错误。我保留了旧的 fileUpload.swffileUpload.fla 文件在源代码中,以防有人仍需要它们。新的 FlashFileUpload.swf 的源代码包含在 FlashFileUpload_src.zip 文件中,该文件包含五个文件。

  • FlashFileUpload.mxml - 主应用程序 GUI
  • components\ApplicationClass.as - 主应用程序代码隐藏
  • components\FileUpload.as - 用于单个文件上传的 FileUpload
  • components\FileUploadEvent.as - 自定义事件类
  • components\FileUploadProgressChangedEvent.as - 自定义事件类

我不会在文章中放入文件的代码,你可以下载它并阅读代码中的注释。另外,一个小声明:我的 ActionScript 经验很少,只有从第一个上传控件到这个控件的经验。我也没有 Flex 经验。这是我第一次接触 Flex。所以,如果我在代码中做了不符合最佳实践的事情,或者可以用其他方式做得更好,那是因为我对 Flex 和 ActionScript 的不熟悉以及我投入的写作时间很少。我对这个控件不作任何保证。希望这篇文章对您有所帮助。

代码并不复杂,并且注释得很好。我现在已经将 Flash 对象生成封装到了一个服务器控件中,并将 FlashFileUpload.swf 文件嵌入到了 DLL 中。有关选项和用法,请参阅 UploadPage 文件夹下的 Default.aspx 中的注释。我包含了限制上传文件类型、限制单个文件大小和总文件大小的选项,这些都可以通过服务器控件进行设置。此外,通过服务器控件还可以轻松设置上传页面、查询参数以及完成时调用的 JavaScript 函数。

我包含了一些使用上传控件的示例。这些示例包括使用 HttpHandler 作为上传页面(比使用 ASPX 页面更轻量)、使用基于表单的身份验证以及使用会话。我将在下面简要介绍每一个示例,但实际代码请参考源代码。

文件的上传是通过 Flash (FlashFileUpload.swf) 完成的,并且可以用于任何服务器端语言,如 PHP、Java、Coldfusion、ASP 等。只要能够处理文件上传,就可以使用 Flash 控件。源代码将详细介绍如何在 ASP.NET 中使用它。

在 ASP.NET 中使用的第一步是将服务器控件添加到 Web 窗体(参见 UploadPage/Default.aspx)并在服务器控件的属性中设置上传页面。上传页面可以是任何能够处理上传文件的页面,甚至是另一个 ASPX 页面。首选方法是使用 HttpHandler,因为它比 ASPX 页面更轻量。对于 HttpHandler,只需要一个实现 IHttpHandler 的类,并在 web.config<httpHandlers> 部分进行一些设置。另外,在 <httpRuntime /> 部分设置 maxRequestLength 也是个好主意,因为这会限制上传到服务器的文件大小。默认值大约是 2 或 4 MB。因此,您应该将其设置为您想要允许的最大上传文件大小。使用上传控件所需的就是这些。其余的代码是用于上述示例的。

Cookie 和 Flash

Flash 在非 Internet Explorer 浏览器中存在一个 bug。根据我所了解,Flash 不会将浏览器中设置的 Cookie 与上传的文件一起发送。这意味着任何使用 Cookie 的功能在上传页面中都将无法访问。因此,会话和基于表单的身份验证在其默认实现中会中断,因为它们使用 Cookie。这通常会导致令人讨厌的 #2038 错误。有一些解决方法。

表单身份验证

要解决使用基于表单的身份验证时 Flash 的 bug 问题,请创建一个文件夹并向其中添加一个 Web 窗体。这将作为上传页面,因此请在此页面中添加上传控件。添加一个 web.config 文件,将该文件夹标记为可供匿名用户访问。然后在 Web 窗体的 Page_Load 事件中,检查用户是否已通过身份验证,如果未通过,则将其发送到登录页面。然后使用以下代码对用户的身份票证进行编码,并将其放入上传控件的查询参数中。

FormsIdentity cIdentity = User.Identity as FormsIdentity;
string encryptString = FormsAuthentication.Encrypt(cIdentity.Ticket);
flashUpload.QueryParameters = string.Format("User={0}", encryptString);

然后,在上传页面中,可以提取身份信息。

string EncryptString = context.Request.QueryString["User"];
FormsAuthenticationTicket UserTicket = FormsAuthentication.Decrypt(EncryptString);

我们还可以检查它是否已过期,甚至获取用户的 username

if(!UserTicket.Expired)
{
    string username = UserTicket.Name;
}

会话

不幸的是,会话处理起来没有那么干净。要使用会话,必须将其设置为无 Cookie 模式。这样做会在 URL 中添加一些乱码。通常这对用户来说是透明的。在 web.config 中进行设置。

<sessionState cookieless="UseUri" />

如果使用 HttpHandler,它还需要实现 IRequiresSessionState

快速说明

源代码解决方案是使用 Visual Studio 2008 构建的,但基于 .NET 2.0。如果您没有 Visual Studio 2008(不确定免费的 Web 开发工具是否可以打开该解决方案),您仍然可以在 Visual Studio 2005 或免费 Web 开发工具中通过“文件”->“打开网站”并浏览到 FlashUpload_Web 文件夹来打开 FlashUpload_Web 目录下的 Web 项目。

历史

  • 2006.09.28 -- 初始发布
  • 2008.07.10 -- 更新源代码
© . All rights reserved.