手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>网络编程>Asp.Net编程>列表

在ASP.NET中跟踪和恢复大文件下载

来源:互联网 作者:west263.com 时间:2008-02-22
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!

  iResponseContentLength = Convert.ToInt32(alRequestedRangesend( _
iLoop) - alRequestedRangesBegin(iLoop)) 1
  If bMultipart Then
   ' 如果是多部分范围请求,计算出将发送的中间头信息的长度
   iResponseContentLength = MULTIPART_BOUNDARY.Length
   iResponseContentLength = objFile.ContentType.Length
   iResponseContentLength = alRequestedRangesBegin(iLoop).ToString.Length
   iResponseContentLength = alRequestedRangesend(iLoop).ToString.Length
   iResponseContentLength = objFile.Length.ToString.Length
   ' 49是多部分下载中换行和其它必要的字符的长度
   iResponseContentLength = 49
  End If
 Next iLoop

 If bMultipart Then
  ' 如果是多部分范围请求,
  ' 我们还必须计算出将发送的最后一个中间头信息的长度
  iResponseContentLength =MULTIPART_BOUNDARY.Length
  ' 8 是破折号和换行符的长度
  iResponseContentLength = 8
 Else
  ' 不是多部分下载,因此我们必须说明初始HTTP头信息的响应范围
  objResponse.AppendHeader( HTTP_HEADER_CONTENT_RANGE, "bytes " & _
  alRequestedRangesBegin(0).ToString & "-" & _
  alRequestedRangesend(0).ToString & "/" & _
  objFile.Length.ToString)
  'End If
  ' 范围响应
  objResponse.StatusCode = 206 ' 局部响应
 Else
  ' 这不是范围请求,或者被请求的范围实体ID与当前的实体ID不匹配,
  ' 因此开始新的下载
  ' 指明文件完成部分的大小等于内容的长度
  iResponseContentLength =Convert.ToInt32(objFile.Length)
  ' 返回正常的OK状态
  objResponse.StatusCode = 200
 End If
 ' 接下来服务器必须发送几个重要的响应头信息,例如内容长度、Etag、和文件的内容类型:
 ' 把内容长度写入响应
 objResponse.AppendHeader( HTTP_HEADER_CONTENT_LENGTH,iResponseContentLength.ToString)
 ' 把最后修改日期写入响应
 objResponse.AppendHeader( HTTP_HEADER_LAST_MODIFIED,objFile.LastWriteTimeUTC.ToString("r"))
 ' 告诉客户端软件我们接受了范围请求
 objResponse.AppendHeader( HTTP_HEADER_ACCEPT_RANGES,HTTP_HEADER_ACCEPT_RANGES_BYTES)
 ' 把文件的实体标签写入响应(用引号括起来)
 objResponse.AppendHeader(HTTP_HEADER_ENTITY_TAG, """" & objFile.EntityTag & """")
 ' 把内容类型写入响应
 If bMultipart Then
  ' 多部分消息有这种特殊的类型
  ' 在例子中文件实际的mime类型在以后才写入响应
  objResponse.ContentType = MULTIPART_CONTENTTYPE
 Else
  ' 单个部分消息拥有的文件内容类型
  objResponse.ContentType = objFile.ContentType
End If


  下载所需要的一切都准备好了,可以开始下载文件了。你将使用FileStream对象从文件中读取字节块。把FileInformation实例objFile的State属性设置为fsDownloadInProgress。只要客户端保持连接,服务器就从文件中读取字节块并发送给客户端。对于多部分下载,这段代码会发送特定的头信息。如果客户端中断连接,服务器就把文件状态设置为fsDownloadBroken。如果服务器完成了被请求范围的发送过程,它会把状态设置为fsDownloadFinished(见下载代码)。

  FileInformation辅助类

  在ZIPHandler部分中你会发现,FileInformation是一个辅助类,它封装了下载状态信息(例如下载中、中断等等)。

  为了建立FileInformation的实例,你需要把被请求文件的路径传递给该类的构造函数:

Public Sub New(ByVal sPath As String)
 m_objFile = New System.IO.FileInfo(sPath)
End Sub

  FileInformation使用System.IO.FileInfo对象来获取文件的信息,这些信息是作为该对象的属性暴露的(例如文件是否存在、文件全名、大小等等)。这个类还暴露了一个DownloadState枚举,它描述了下载请求的多种状态:

Enum DownloadState
 ' Clear:没有下载过程,文件可能在维护
 fsClear = 1
 ' Locked:动态建立的文件不能被更改
 fsLocked = 2
 ' In Progress:文件被锁定了,下载过程正在进行
 fsDownloadInProgress = 6
 ' Broken:文件被锁定了,下载过程正在进行,但是被取消了
 fsDownloadBroken = 10
 ' Finished:文件被锁定了,下载过程完成了
 fsDownloadFinished = 18
End Enum

  FileInformation还提供了EntityTag属性值。示例代码中的这个值是硬编码的,这是由于示例代码只使用了一个下载文件,并且该文件不会被改变,但是对于实际应用程序来说,你会提供多个文件,甚至于动态地建立文件,你的代码必须为每个文件提供一个唯一的EntityTag值。此外,每次改变或修改该文件的时候,这个值也必须改变。这使客户端软件能够验证它们已经下载的字节块是否仍然是最新的。下面是示例代码中返回硬编码EntityTag值的部分:

Public ReadOnly Property EntityTag() As String
 ' EntityTag用于对客户端的初始(200)响应,以及来自客户端的恢复请求
 Get
  ' 为文件建立唯一的字符串。
  ' 注意,只要文件没有发生改变,该唯一码就必须保留。
  ' 但是,如果文件的确改变了或者被修改了,这个码必须改变。
  Return "MyExampleFileID"
 End Get
End Property

  一个简单的和大致足够安全的EntityTag可能由文件名和文件最后被修改的日期组成。无论使用什么方法,你都必须确保这个值是真的是唯一的,不会与其它文件的EntityTag混淆。我希望在自己的应用程序中按照客户、顾客和邮编索引来动态地替被建立的文件命名,并把用作EntityTag的GUID存储在数据库中。

  ZipFileHandler类读取和设置公共的State属性。在完成下载以后,它把State设置为fsDownloadFinished。这个时候你就可以删除临时文件了。这儿一般需要调用Save方法来维持状态。

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!