FileInformation uses a System.IO.FileInfo object to get information about that file, which it exposes as properties, for example, whether the file exists, its full name, size, etc. The class also exposes a
DownloadState enumeration that describes the various states of a download request:
<Flags()> Enum DownloadState
' Clear: No download in progress,
' the file can be manipulated
fsClear = 1
' Locked: A dynamically created file must
' not be changed
fsLocked = 2
' In Progress: File is locked, and download
' is currently in progress
fsDownloadInProgress = 6
' Broken: File is locked, download was in
' progress, but was cancelled
fsDownloadBroken = 10
' Finished: File is locked, download
' was completed
fsDownloadFinished = 18
End Enum
FileInformation also provides the
EntityTag property value. The
sample code has a hard-coded value in it, because the sample uses only one download file, which will not be changed, but for a real-world application, where you're serving multiple files, or even create files dynamically, your code must provide unique
EntityTag values for each file. Plus, each time that you change or edit the file that value must change as well. This enables client software to verify if the chunk they downloaded before is still up-to-date. Here's the section that returns the hard-coded
EntityTag value in the sample code.
Public ReadOnly Property EntityTag() As String
' The EntityTag used in the initial (200) response
' to, and in resume-Requests from clients
Get
' ToDo - your code here
' (Create a unique string for your file)
'
' Please note, that this unique code must remain
' the same as long as the file does not change.
' If the file DOES change or is edited, however,
' the code MUST change.
Return "MyExampleFileID"
End Get
End Property
A simple and probably safe enough
EntityTag could be a combination of the file name and the file's last modified date. Whatever method you choose, please make sure that it is truly unique and can't be confused with another file's
EntityTag. I prefer to name dynamically created files in my applications after the client, customer, and zip queue indexes, and use a GUID saved in a database for the
EntityTag.
The ZipFileHandler reads and sets the public
State property. After a completed download, it sets
State to
fsDownloadFinished. At that point you can delete temporary files. Always call the
Save method here, to persist the state.
Public Property State() As DownloadState
Get
Return m_nState
End Get
Set(ByVal nState As DownloadState)
m_nState = nState
' ToDo - optional
' At this point, you could delete the
' file automatically.
' If the state is set to Finished, you
' might not need the file anymore:
' If nState = _
' DownloadState.fsDownloadFinished Then
' Clear()
' Else
' Save()
' End If
Save()
End Set
End Property
The ZipFileHandler should call the
Save method whenever the file state changes, saving the file's state, so it can be displayed to the user at a later time. You can also use it to save the
EntityTag you created. Do not save the file's state and
EntityTag value to the Application, Session, or Cacheyou must persist that information across any of those lifecycles.
Private Sub Save()
' ToDo - your code here
' Save the state of this file's download
' to a database or XML file...)
'
' If you do not create files dynamically,
' you do not need to save the state, of course.
End Sub
As written, the
sample code handles only one existing file (
download.zip); however you can enhance it to create requested files on demand.
When testing the sample code, your local system or LAN will probably be too fast to interrupt the download, so I recommend you use either a slow LAN connection (one way to simulate one is to reduce your site's bandwidth in IIS) or a live server on the Internet.
Downloading can still be tough on the client side. Broken or misconfigured Web cache servers operated by ISPs can ruin large downloads, inducing corruption or early session termination. If your files exceed 255 MB in size, you might want to encourage your customers to use third-party download manager software, although some newer browsers have basic download managers built-in.
If you want to extend the sample code even more, it's worth taking another look at the HTTP specifications. You could create MD5 digest values for the download, and add them using Content-MD5 header, providing a way to check the integrity of the download. The sample doesn't cover HTTP methods other than GET and HEAD, either.