如何下载文件...帮助 [英] How to download a file...HELP
问题描述
Hwllo,请任何人提供经验丰富的帮助. 我正在尝试制作一个从列表视图中单击的项目构建其文件列表的下载器.
Hwllo, please i need an experienced help from anyone. I am trying to make a downloader that builds its list of files from the clicked items in a listview.
我面临的问题是我正在使用的类仅下载一个文件并拒绝循环浏览列表.
The problem i am facing is that the class i am using just download a single file and refuse to loop through the list.
请给我帮助,因为这是我的学校项目.
Plase i need help as this is my school project.
< b>我的代码:</b>
<b>MY CODE:</b>
< b>下载类</b>
<b>THE DOWNLOAD CLASS</b>
严格启用选项:显式启用
导入System.ComponentModel
导入System.IO
导入System.Net
命名空间Joe_Download_Class
#Region公共类FileDownloader"
'''< summary>类用于在后台下载文件,该文件支持有关其进度,总进度,取消,暂停和恢复的信息.下载将在单独的线程上运行,因此您不必担心多重读取
你自己. </summary>
'''< remarks> Class FileDownloader v1.0.3,由De Dauw Jeroen撰写-2009年5月</remarks>
公共类FileDownloader
继承System.Object
实现IDisposable
#Region嵌套类型"
#Region公共结构FileInfo"
'''< summary>用于管理文件信息的简单结构</summary>
公共结构FileInfo
'''< summary>文件的完整路径(目录+文件名)</summary>
公用路径为字符串
'''< summary>文件名</summary>
公用名称为字符串
'''< summary>创建FileInfo的新实例</summary>
'''< param name =路径">文件的完整路径(目录+文件名)</param>
Public Sub New(ByVal路径为字符串)
Me.Path =路径
Me.Name = Me.Path.Split("/" c)(Me.Path.Split("/" c).Length-1)
结束子
端部结构
#End Region
#Region私人枚举[事件]"
'''< summary>用于在后台工作程序中触发但需要在主线程中触发的事件的</summary>
私人枚举[事件]
CalculationFileSizesStarted
FileSizesCalculationComplete
取消取消后删除文件
FileDownloadAttempting
FileDownloadStarted
FileDownloadStopped
FileDownloadSucceeded
ProgressChanged
结束枚举
#End Region
#Region私人枚举InvokeType"
'''< summary>需要执行的操作的持有者</summary>
私有枚举InvokeType
EventRaiser
FileDownloadFailedRaiser
CalculatingFileNrRaiser
结束枚举
#End Region
#End Region
#Region事件"
'''< summary>在文件下载开始时出现</summary>
以EventHandler开头的公共事件
'''< summary>在文件下载被暂停时发生</summary>
暂停为EventHandler的公共事件
'''< summary>在恢复文件下载后发生</summary>
恢复为EventHandler的公共事件
'''< summary>在用户请求取消下载时发生</summary>
公共事件CancelRequested为EventHandler
'''< summary>在用户请求取消下载并且已开始清理下载的文件时出现</summary>
公共事件DeletingFilesAfterCancel作为EventHandler
'''< summary>在用户取消文件下载时发生</summary>
公共事件已取消为EventHandler
'''< summary>在文件下载完成时(不取消取消)发生</summary>
作为EventHandler完成的公共事件
'''< summary>在通过取消或完成而停止文件下载时发生</summary>
公共事件已作为EventHandler停止
'''< summary>在FileDownloader的繁忙状态更改时发生</summary>
将公共事件IsBusyChanged更改为EventHandler
'''< summary>在FileDownloader的暂停状态已更改时发生</summary>
公共事件IsPausedChanged作为EventHandler
'''< summary>在FileDownloader的繁忙或暂停状态更改时发生</summary>
公共事件StateChanged为EventHandler
'''< summary>在开始计算文件大小时发生</summary>
公共事件CalculationFileSizes开始为EventHandler
'''< summary>在开始计算文件大小时发生</summary>
公共事件CalculatingFileSize作为FileSizeCalculationEventHandler
'''< summary>在文件大小的计算完成后发生</summary>
公共事件FileSizesCalculationComplete作为EventHandler
'''< summary>在FileDownloader尝试获取Web响应以下载文件时发生</summary>
公共事件FileDownloadAttempting作为EventHandler
'''< summary>在文件下载开始时出现</summary>
公共事件FileDownloadStarted作为EventHandler
'''< summary>在文件下载停止时发生</summary>
公共事件FileDownloadStopped作为EventHandler
'''< summary>在文件下载成功完成时发生</summary>
公共事件文件下载成功为EventHandler
'''< summary>在文件下载未成功完成时发生</summary>
公共事件FileDownloadFailed(ByVal发送者为对象,ByVal e为例外)
'''< summary>每次下载数据块时都会出现</summary>
公共事件ProgressChanged更改为EventHandler
#End Region
#Region字段"
公共委托子FileSizeCalculationEventHandler(ByVal发送者为对象,ByVal文件编号为Int32)
私人WithEvents bgwDownloader作为新的BackgroundWorker
私有触发器作为新Threading.ManualResetEvent(True)
'首选项
私有m_supportsProgress,m_deleteCompletedFiles为布尔值
私有m_packageSize,m_stopWatchCycles作为Int32
州
私有m_disposed为Boolean = False
私有m_busy,m_paused,m_canceled为布尔值
私有m_currentFileProgress,m_totalProgress,m_currentFileSize为Int64
私有m_currentSpeed,m_fileNr作为Int32
数据
私有m_localDirectory作为字符串
私有m_files作为新列表(文件信息)
私有m_totalSize为Int64
#End Region
#Region构造函数"
'''< summary>创建FileDownloader的新实例</summary>
'''< param name =" supportsProgress">可选.布尔值. FileDownloader应该支持总进度统计吗?</param>
Public Sub New(可选,ByVal支持Progress As Boolean = False)
'设置bgw属性
bgwDownloader.WorkerReportsProgress = True
bgwDownloader.WorkerSupportsCancellation = True
'设置默认的班级偏好设置
Me.SupportsProgress = supportsProgress
Me.PackageSize = 4096
Me.StopWatchCyclesAmount = 5
Me.DeleteCompletedFilesAfterCancel = False
结束子
#End Region
#Region公共方法"
'''< summary>开始下载</summary>
Public Sub Start()
Me.IsBusy = True
结束子
'''< summary>暂停下载</summary>
公开子暂停()
Me.IsPaused = True
结束子
'''< summary>恢复下载</summary>
Public Sub [Resume]()
Me.IsPaused = False
结束子
'''< summary>停止下载</summary>
公共重载子项[Stop]()
Me.IsBusy = False
结束子
'''< summary>停止下载</summary>
'''< param name =" deleteCompletedFiles">是必需的.布尔值.表示是否应删除完整的下载文件</param>
公共重载子项[Stop](ByVal deleteCompletedFiles为布尔值)
Me.DeleteCompletedFilesAfterCancel = deleteCompletedFiles
Me.Stop()
结束子
'''< summary>发布FileDownloader拥有的资源</summary>
Public Sub Dispose()实现IDisposable.Dispose
处置(真实)
GC.SuppressFinalize(Me)
结束子
'''< summary>使用二进制符号符号</summary>
将一定数量的字节格式化为更易读的符号
'''< param name =大小">是必需的. Int64.原始字节数</param>
'''< param name =十进制">可选. Int32.您希望在符号</param>
中显示的小数位数
公共共享函数FormatSizeBinary(ByVal大小为Int64,可选的ByVal小数作为Int32 = 2)作为字符串
由De Dauw Jeroen撰写-2009年4月-jeroen_dedauw@yahoo.com
Dim size()As String = {"B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"}}
昏暗formattedSize为Double = size
Dim sizeIndex As Int32 = 0
而formattedSize> = 1024并且sizeIndex<尺寸.长度
formattedSize/= 1024
sizeIndex + = 1
结束时
返回Math.Round(formattedSize,小数点).ToString&大小(sizeIndex)
结束功能
'''< summary>使用十进制表示法符号</summary>
将一定数量的字节格式化为更易读的表示法
'''< param name =大小">是必需的. Int64.原始字节数</param>
'''< param name =十进制">可选. Int32.您希望在符号</param>
中显示的小数位数
公共共享函数FormatSizeDecimal(ByVal大小为Int64,可选的ByVal小数为Int32 = 2)作为字符串
由De Dauw Jeroen撰写-2009年4月-jeroen_dedauw@yahoo.com
Dim Sizes()As String = {"B","kB","MB","GB","TB","PB","EB","ZB","YB"}}
昏暗formattedSize为Double = size
Dim sizeIndex As Int32 = 0
而formattedSize> = 1000而sizeIndex<尺寸.长度
formattedSize/= 1000
sizeIndex + = 1
结束时
返回Math.Round(formattedSize,小数点).ToString&大小(sizeIndex)
结束功能
#End Region
#Region私有/受保护的方法"
私人子bgwDownloader_DoWork()处理bgwDownloader.DoWork
Dim fileNr As Int32 = 0
如果是Me.SupportsProgress,则calculateFilesSize()
如果不是Directory.Exists(Me.LocalDirectory),则Directory.CreateDirectory(Me.LocalDirectory)
而fileNr< Me.Files.Count而不是bgwDownloader.CancellationPending
m_fileNr = fileNr
downloadFile(fileNr)
如果是bgwDownloader.CancellationPending则
fireEventFromBgw([Event] .DeletingFilesAfterCancel)
cleanUpFiles(If(Me.DeleteCompletedFilesAfterCancel,0,m_fileNr),If(Me.DeleteCompletedFilesAfterCancel,m_fileNr + 1,1))
其他
fileNr + = 1
如果结束
结束时
结束子
Private Sub fireEventFromBgw(ByVal eventName As [Event])
bgwDownloader.ReportProgress(InvokeType.EventRaiser,eventName)
结束子
私人Sub bwgDownloader_ProgressChanged(ByVal发送者作为对象,ByVal e作为ProgressChangedEventArgs)处理bgwDownloader.ProgressChanged
选择案例CType(e.ProgressPercentage,InvokeType)
Case InvokeType.EventRaiser
选择大小写CType(e.UserState,[Event])
案例[Event] .CalculationFileSizesStarted
RaiseEvent CalculationFileSizesStarted(Me,New EventArgs)
案例[Event] .FileSizesCalculationComplete
RaiseEvent FileSizesCalculationComplete(Me,New EventArgs)
案例[事件] .DeletingFilesAfterCancel
RaiseEvent DeletingFilesAfterCancel(Me,New EventArgs)
案例[事件] .FileDownloadAttempting
RaiseEvent FileDownloadAttempting(Me,New EventArgs)
案例[事件] .FileDownloadStarted
RaiseEvent FileDownloadStarted(Me,New EventArgs)
案例[事件] .FileDownloadStopped
RaiseEvent FileDownloadStopped(Me,New EventArgs)
案例[事件] .FileDownloadSucceeded
RaiseEvent FileDownloadSucceeded(Me,New EventArgs)
案例[事件] .ProgressChanged
RaiseEvent ProgressChanged(Me,New EventArgs)
结束选择
Case InvokeType.FileDownloadFailedRaiser
RaiseEvent FileDownloadFailed(Me,CType(e.UserState,Exception))
Case InvokeType.CalculatingFileNrRaiser
RaiseEvent CalculatingFileSize(Me,CInt(e.UserState))
结束选择
结束子
Private Sub cleanUpFiles(可选,以Int32 = 0开头的ByVal,可选,以Int32 = -1开头的ByVal长度)
Int32 = In(32
Dim fullPath As String = Me.LocalDirectory& "\" & Me.Files(fileNr).Name
如果IO.File.Exists(fullPath),则IO.File.Delete(fullPath)
下一个
结束子
私人子calculateFilesSize()
fireEventFromBgw([Event] .CalculationFileSizesStarted)
m_totalSize = 0
对于FileNr As Int32 = 0 To Me.Files.Count-1
bgwDownloader.ReportProgress(InvokeType.CalculatingFileNrRaiser,fileNr + 1)
试试
昏暗的webReq为HttpWebRequest = CType(Net.WebRequest.Create(Me.Files(fileNr).Path),HttpWebRequest)
暗淡的webResp为HttpWebResponse = CType(webReq.GetResponse,HttpWebResponse)
m_totalSize + = webResp.ContentLength
webResp.Close()
异常捕获
结束尝试
下一个
fireEventFromBgw([Event] .FileSizesCalculationComplete)
结束子
专用子downloadFile(ByVal fileNr As Int32)
m_currentFileSize = 0
fireEventFromBgw([Event] .FileDownloadAttempting)
昏暗的文件为FileInfo = Me.Files(fileNr)
Dim大小为Int64 = 0
Dim readBytes(Me.PackageSize-1)作为字节
将currentPackageSize设置为Int32昏暗
昏暗的作家作为新的FileStream(Me.LocalDirectory&"\"& file.Name,IO.FileMode.Create)
昏暗的SpeedTimer作为新的秒表
昏暗的读数为Int32 = 0
昏暗的例外情况
暗淡的webReq为HttpWebRequest
将webResp设置为HttpWebResponse
试试
webReq = CType(Net.WebRequest.Create(Me.Files(fileNr).Path),HttpWebRequest)
webResp = CType(webReq.GetResponse,HttpWebResponse)
大小= webResp.ContentLength
异常捕获
排除= ex
结束尝试
m_currentFileSize =大小
fireEventFromBgw([Event] .FileDownloadStarted)
如果exc什么都没有,那么
bgwDownloader.ReportProgress(InvokeType.FileDownloadFailedRaiser,排除)
其他
m_currentFileProgress = 0
而m_currentFileProgress<尺寸
如果是bgwDownloader.CancellationPending则
speedTimer.Stop()
writer.Close()
webResp.Close()
退出子
如果结束
trigger.WaitOne()
speedTimer.Start()
currentPackageSize = webResp.GetResponseStream().Read(readBytes,0,Me.PackageSize)
m_currentFileProgress + = currentPackageSize
m_totalProgress + = currentPackageSize
fireEventFromBgw([Event] .ProgressChanged)
writer.Write(readBytes,0,currentPackageSize)
读数+ = 1
如果读数> = Me.StopWatchCyclesAmount然后
m_currentSpeed = CInt(Me.PackageSize * StopWatchCyclesAmount * 1000/(speedTimer.ElapsedMilliseconds +1))
speedTimer.Reset()
读数= 0
如果结束
结束时
speedTimer.Stop()
writer.Close()
webResp.Close()
fireEventFromBgw([Event] .FileDownloadSucceeded)
如果结束
fireEventFromBgw([Event] .FileDownloadStopped)
结束子
私人Sub bgwDownloader_RunWorkerCompleted(ByVal发送者作为对象,ByVal e作为System.ComponentModel.RunWorkerCompletedEventArgs)处理bgwDownloader.RunWorkerCompleted
Me.IsPaused = False
m_busy = False
如果是Me.HasBeen取消了
RaiseEvent已取消(我,新的EventArgs)
其他
RaiseEvent Completed(我,New EventArgs)
如果结束
RaiseEvent Stopped(Me,New EventArgs)
RaiseEvent IsBusyChanged(Me,New EventArgs)
RaiseEvent StateChanged(Me,New EventArgs)
结束子
受保护的可重写子Dispose(ByVal以布尔方式进行处置)
如果不是m_disposed然后
如果要处理的话
'释放其他状态(托管对象)
bgwDownloader.Dispose()
如果结束
'释放自己的状态(非托管对象)
'将大字段设置为空
Me.Files = Nothing
如果结束
m_disposed =真实
结束子
#End Region
#Region属性"
'''< summary>获取或设置要下载的文件列表</summary>
公共属性Files()作为List(Of FileInfo)
获取
返回m_files
结束获取
Set(ByVal值作为List(Of FileInfo))
如果我很忙的话
引发New InvalidOperationException(您在下载过程中不能更改文件列表")
其他
如果Me.Files不是值,则m_files =值
如果结束
端套
最终财产
'''< summary>获取或设置要在其中存储文件的本地目录</summary>
公共属性LocalDirectory()作为字符串
获取
返回m_localDirectory
结束获取
设置(ByVal值作为字符串)
如果值<> Me.LocalDirectory然后
m_localDirectory =值
如果结束
端套
最终财产
'''< summary>获取或设置FileDownloader是否应支持总进度统计信息.请注意,启用后,FileDownloader必须先获取每个文件的大小,然后才能开始下载它们,这可能会延迟
操作.</summary>
公共属性SupportsProgress()为布尔值
获取
返回m_supportsProgress
结束获取
设置(ByVal值作为布尔值)
如果我很忙的话
抛出新的InvalidOperationException(下载期间您不能更改SupportsProgress属性")
其他
m_supportsProgress =值
如果结束
端套
最终财产
'''< summary>获取或设置在取消下载过程时是否应删除完整的下载文件</summary>
公共属性DeleteCompletedFilesAfterCancel()作为Boolean
获取
返回m_deleteCompletedFiles
结束获取
设置(ByVal值作为布尔值)
m_deleteCompletedFiles =值
端套
最终财产
'''< summary>获取或设置将要下载的块的大小</summary>
公共属性PackageSize()为Int32
获取
返回m_packageSize
结束获取
设置(ByVal值作为Int32)
如果值> 0然后
m_packageSize =值
其他
引发New InvalidOperationException("PackageSize需要更大,然后变为0")
如果结束
端套
最终财产
'''< summary>获取或设置在重新计算进度速度之前需要下载的块数.注意:将此值设置为较低的值可能会降低准确度</summary>
公共属性StopWatchCyclesAmount()作为Int32
获取
返回m_stopWatchCycles
结束获取
设置(ByVal值作为Int32)
如果值> 0然后
m_stopWatchCycles =值
其他
引发New InvalidOperationException("StopWatchCyclesAmount需要更大,然后再设为0")
如果结束
端套
最终财产
'''< summary>获取或设置FileDownloader的繁忙状态</summary>
公共属性IsBusy()为布尔值
获取
返回m_busy
结束获取
设置(ByVal值作为布尔值)
如果Me.IsBusy<>值然后
m_busy =值
m_canceled =没有值
如果我很忙的话
m_totalProgress = 0
bgwDownloader.RunWorkerAsync()
RaiseEvent Started(我,新的EventArgs)
RaiseEvent IsBusyChanged(Me,New EventArgs)
RaiseEvent StateChanged(Me,New EventArgs)
其他
m_paused = False
bgwDownloader.CancelAsync()
RaiseEvent CancelRequested(Me,New EventArgs)
RaiseEvent StateChanged(Me,New EventArgs)
如果结束
如果结束
端套
最终财产
'''< summary>获取或设置FileDownloader的暂停状态</summary>
公共属性IsPaused()为布尔值
获取
返回m_paused
结束获取
设置(ByVal值作为布尔值)
如果我很忙的话
如果值<>我被暂停了
m_paused =值
如果我被暂停
trigger.Reset()
RaiseEvent Paused(Me,New EventArgs)
其他
trigger.Set()
已恢复RaiseEvent(我,新的EventArgs)
如果结束
RaiseEvent IsPausedChanged(Me,New EventArgs)
RaiseEvent StateChanged(Me,New EventArgs)
如果结束
如果结束
端套
最终财产
'''< summary>获取FileDownloader是否可以启动</summary>
布尔值的公共ReadOnly属性CanStart()
获取
返回不是我.IsBusy
结束获取
最终财产
'''< summary>获取FileDownloader是否可以暂停</summary>
布尔值的公共ReadOnly属性CanPause()
获取
返回我.忙碌而不是我.已暂停而不是bgwDownloader.CancellationPending
结束获取
最终财产
'''< summary>获取FileDownloader是否可以恢复</summary>
布尔值的公共ReadOnly属性CanResume()
获取
返回Me.IsBusy和Me.IsPaused,而不是bgwDownloader.CancellationPending
结束获取
最终财产
'''< summary>获取FileDownloader是否可以停止</summary>
布尔值的公共ReadOnly属性CanStop()
获取
返回Me.IsBusy而不是bgwDownloader.CancellationPending
结束获取
最终财产
'''< summary>一起获取所有文件的总大小.仅在FileDownloader支持进度</summary>
时可用
公开的只读属性TotalSize()为Int64
获取
如果是Me.SupportsProgress然后
返回m_totalSize
其他
抛出New InvalidOperationException(此FileDownloader,它不支持进度.修改SupportsProgress以声明它确实支持进度以获取总大小.")
如果结束
结束获取
最终财产
'''< summary>获取下载的字节总数</summary>
以Int64形式公开的ReadOnly属性TotalProgress()
获取
返回m_totalProgress
结束获取
最终财产
'''< summary>获取当前文件的下载字节数</summary>
公共只读属性CurrentFileProgress()作为Int64
获取
返回m_currentFileProgress
结束获取
最终财产
'''< summary>获取总下载百分比.仅在FileDownloader支持进度</summary>
时可用
公共ReadOnly属性TotalPercentage(作为Int32 = 0的ByVal小数)作为Double
获取
如果是Me.SupportsProgress然后
返回Math.Round(Me.TotalProgress/Me.TotalSize * 100,十进制)
其他
抛出新的InvalidOperationException(此FileDownloader,它不支持进度.修改SupportsProgress以声明它确实支持进度.")
如果结束
结束获取
最终财产
'''< summary>获取当前文件进度的百分比</summary>
公共ReadOnly属性CurrentFilePercentage(可选的ByVal小数,作为Int32 = 0)作为Double
获取
返回Math.Round(Me.CurrentFileProgress/Me.CurrentFileSize * 100,十进制)
结束获取
最终财产
'''< summary>获取当前下载速度(以字节为单位)</summary>
以Int32形式公开的ReadOnly属性DownloadSpeed()
获取
返回m_currentSpeed
结束获取
最终财产
'''< summary>获取代表当前文件的FileInfo对象</summary>
公共ReadOnly属性CurrentFile()作为FileInfo
获取
返回Me.Files(m_fileNr)
结束获取
最终财产
'''< summary>获取当前文件的大小(以字节为单位)</summary>
公共只读属性CurrentFileSize()作为Int64
获取
返回m_currentFileSize
结束获取
最终财产
'''< summary>获取用户是否取消了上一次下载</summary>
私有ReadOnly属性HasBeenCanceled()为布尔值
获取
返回m_canceled
结束获取
最终财产
#End Region
结束类
#End Region
结束命名空间
Option Strict On : Option Explicit On
Imports System.ComponentModel
Imports System.IO
Imports System.Net
Namespace Joe_Download_Class
#Region "Public Class FileDownloader"
''' <summary>Class for downloading files in the background that supports info about their progress, the total progress, cancellation, pausing, and resuming. The downloads will run on a separate thread so you don't have to worry about multihreading
yourself. </summary>
''' <remarks>Class FileDownloader v1.0.3, by De Dauw Jeroen - May 2009</remarks>
Public Class FileDownloader
Inherits System.Object
Implements IDisposable
#Region "Nested types"
#Region "Public Structure FileInfo"
''' <summary>Simple structure for managing file info</summary>
Public Structure FileInfo
''' <summary>The complete path of the file (directory + filename)</summary>
Public Path As String
''' <summary>The name of the file</summary>
Public Name As String
''' <summary>Create a new instance of FileInfo</summary>
''' <param name="path">The complete path of the file (directory + filename)</param>
Public Sub New(ByVal path As String)
Me.Path = path
Me.Name = Me.Path.Split("/"c)(Me.Path.Split("/"c).Length - 1)
End Sub
End Structure
#End Region
#Region "Private Enum [Event]"
''' <summary>Holder for events that are triggered in the background worker but need to be fired in the main thread</summary>
Private Enum [Event]
CalculationFileSizesStarted
FileSizesCalculationComplete
DeletingFilesAfterCancel
FileDownloadAttempting
FileDownloadStarted
FileDownloadStopped
FileDownloadSucceeded
ProgressChanged
End Enum
#End Region
#Region "Private Enum InvokeType"
''' <summary>Holder for the action that needs to be invoked</summary>
Private Enum InvokeType
EventRaiser
FileDownloadFailedRaiser
CalculatingFileNrRaiser
End Enum
#End Region
#End Region
#Region "Events"
''' <summary>Occurs when the file downloading has started</summary>
Public Event Started As EventHandler
''' <summary>Occurs when the file downloading has been paused</summary>
Public Event Paused As EventHandler
''' <summary>Occurs when the file downloading has been resumed</summary>
Public Event Resumed As EventHandler
''' <summary>Occurs when the user has requested to cancel the downloads</summary>
Public Event CancelRequested As EventHandler
''' <summary>Occurs when the user has requested to cancel the downloads and the cleanup of the downloaded files has started</summary>
Public Event DeletingFilesAfterCancel As EventHandler
''' <summary>Occurs when the file downloading has been canceled by the user</summary>
Public Event Canceled As EventHandler
''' <summary>Occurs when the file downloading has been completed (without canceling it)</summary>
Public Event Completed As EventHandler
''' <summary>Occurs when the file downloading has been stopped by either cancellation or completion</summary>
Public Event Stopped As EventHandler
''' <summary>Occurs when the busy state of the FileDownloader has changed</summary>
Public Event IsBusyChanged As EventHandler
''' <summary>Occurs when the pause state of the FileDownloader has changed</summary>
Public Event IsPausedChanged As EventHandler
''' <summary>Occurs when the either the busy or pause state of the FileDownloader have changed</summary>
Public Event StateChanged As EventHandler
''' <summary>Occurs when the calculation of the file sizes has started</summary>
Public Event CalculationFileSizesStarted As EventHandler
''' <summary>Occurs when the calculation of the file sizes has started</summary>
Public Event CalculatingFileSize As FileSizeCalculationEventHandler
''' <summary>Occurs when the calculation of the file sizes has been completed</summary>
Public Event FileSizesCalculationComplete As EventHandler
''' <summary>Occurs when the FileDownloader attempts to get a web response to download the file</summary>
Public Event FileDownloadAttempting As EventHandler
''' <summary>Occurs when a file download has started</summary>
Public Event FileDownloadStarted As EventHandler
''' <summary>Occurs when a file download has stopped</summary>
Public Event FileDownloadStopped As EventHandler
''' <summary>Occurs when a file download has been completed successfully</summary>
Public Event FileDownloadSucceeded As EventHandler
''' <summary>Occurs when a file download has been completed unsuccessfully</summary>
Public Event FileDownloadFailed(ByVal sender As Object, ByVal e As Exception)
''' <summary>Occurs every time a block of data has been downloaded</summary>
Public Event ProgressChanged As EventHandler
#End Region
#Region "Fields"
Public Delegate Sub FileSizeCalculationEventHandler(ByVal sender As Object, ByVal fileNumber As Int32)
Private WithEvents bgwDownloader As New BackgroundWorker
Private trigger As New Threading.ManualResetEvent(True)
' Preferences
Private m_supportsProgress, m_deleteCompletedFiles As Boolean
Private m_packageSize, m_stopWatchCycles As Int32
' State
Private m_disposed As Boolean = False
Private m_busy, m_paused, m_canceled As Boolean
Private m_currentFileProgress, m_totalProgress, m_currentFileSize As Int64
Private m_currentSpeed, m_fileNr As Int32
' Data
Private m_localDirectory As String
Private m_files As New List(Of FileInfo)
Private m_totalSize As Int64
#End Region
#Region "Constructors"
''' <summary>Create a new instance of a FileDownloader</summary>
''' <param name="supportsProgress">Optional. Boolean. Should the FileDownloader support total progress statistics?</param>
Public Sub New(Optional ByVal supportsProgress As Boolean = False)
' Set the bgw properties
bgwDownloader.WorkerReportsProgress = True
bgwDownloader.WorkerSupportsCancellation = True
' Set the default class preferences
Me.SupportsProgress = supportsProgress
Me.PackageSize = 4096
Me.StopWatchCyclesAmount = 5
Me.DeleteCompletedFilesAfterCancel = False
End Sub
#End Region
#Region "Public methods"
''' <summary>Start the downloads</summary>
Public Sub Start()
Me.IsBusy = True
End Sub
''' <summary>pause the downloads</summary>
Public Sub Pause()
Me.IsPaused = True
End Sub
''' <summary>Resume the downloads</summary>
Public Sub [Resume]()
Me.IsPaused = False
End Sub
''' <summary>Stop the downloads</summary>
Public Overloads Sub [Stop]()
Me.IsBusy = False
End Sub
''' <summary>Stop the downloads</summary>
''' <param name="deleteCompletedFiles">Required. Boolean. Indicates wether the complete downloads should be deleted</param>
Public Overloads Sub [Stop](ByVal deleteCompletedFiles As Boolean)
Me.DeleteCompletedFilesAfterCancel = deleteCompletedFiles
Me.Stop()
End Sub
''' <summary>Release the recources held by the FileDownloader</summary>
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
''' <summary>Format an amount of bytes to a more readible notation with binary notation symbols</summary>
''' <param name="size">Required. Int64. The raw amount of bytes</param>
''' <param name="decimals">Optional. Int32. The amount of decimals you want to have displayed in the notation</param>
Public Shared Function FormatSizeBinary(ByVal size As Int64, Optional ByVal decimals As Int32 = 2) As String
' By De Dauw Jeroen - April 2009 - jeroen_dedauw@yahoo.com
Dim sizes() As String = {"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
Dim formattedSize As Double = size
Dim sizeIndex As Int32 = 0
While formattedSize >= 1024 And sizeIndex < sizes.Length
formattedSize /= 1024
sizeIndex += 1
End While
Return Math.Round(formattedSize, decimals).ToString & sizes(sizeIndex)
End Function
''' <summary>Format an amount of bytes to a more readible notation with decimal notation symbols</summary>
''' <param name="size">Required. Int64. The raw amount of bytes</param>
''' <param name="decimals">Optional. Int32. The amount of decimals you want to have displayed in the notation</param>
Public Shared Function FormatSizeDecimal(ByVal size As Int64, Optional ByVal decimals As Int32 = 2) As String
' By De Dauw Jeroen - April 2009 - jeroen_dedauw@yahoo.com
Dim sizes() As String = {"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
Dim formattedSize As Double = size
Dim sizeIndex As Int32 = 0
While formattedSize >= 1000 And sizeIndex < sizes.Length
formattedSize /= 1000
sizeIndex += 1
End While
Return Math.Round(formattedSize, decimals).ToString & sizes(sizeIndex)
End Function
#End Region
#Region "Private/protected methods"
Private Sub bgwDownloader_DoWork() Handles bgwDownloader.DoWork
Dim fileNr As Int32 = 0
If Me.SupportsProgress Then calculateFilesSize()
If Not Directory.Exists(Me.LocalDirectory) Then Directory.CreateDirectory(Me.LocalDirectory)
While fileNr < Me.Files.Count And Not bgwDownloader.CancellationPending
m_fileNr = fileNr
downloadFile(fileNr)
If bgwDownloader.CancellationPending Then
fireEventFromBgw([Event].DeletingFilesAfterCancel)
cleanUpFiles(If(Me.DeleteCompletedFilesAfterCancel, 0, m_fileNr), If(Me.DeleteCompletedFilesAfterCancel, m_fileNr + 1, 1))
Else
fileNr += 1
End If
End While
End Sub
Private Sub fireEventFromBgw(ByVal eventName As [Event])
bgwDownloader.ReportProgress(InvokeType.EventRaiser, eventName)
End Sub
Private Sub bwgDownloader_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) Handles bgwDownloader.ProgressChanged
Select Case CType(e.ProgressPercentage, InvokeType)
Case InvokeType.EventRaiser
Select Case CType(e.UserState, [Event])
Case [Event].CalculationFileSizesStarted
RaiseEvent CalculationFileSizesStarted(Me, New EventArgs)
Case [Event].FileSizesCalculationComplete
RaiseEvent FileSizesCalculationComplete(Me, New EventArgs)
Case [Event].DeletingFilesAfterCancel
RaiseEvent DeletingFilesAfterCancel(Me, New EventArgs)
Case [Event].FileDownloadAttempting
RaiseEvent FileDownloadAttempting(Me, New EventArgs)
Case [Event].FileDownloadStarted
RaiseEvent FileDownloadStarted(Me, New EventArgs)
Case [Event].FileDownloadStopped
RaiseEvent FileDownloadStopped(Me, New EventArgs)
Case [Event].FileDownloadSucceeded
RaiseEvent FileDownloadSucceeded(Me, New EventArgs)
Case [Event].ProgressChanged
RaiseEvent ProgressChanged(Me, New EventArgs)
End Select
Case InvokeType.FileDownloadFailedRaiser
RaiseEvent FileDownloadFailed(Me, CType(e.UserState, Exception))
Case InvokeType.CalculatingFileNrRaiser
RaiseEvent CalculatingFileSize(Me, CInt(e.UserState))
End Select
End Sub
Private Sub cleanUpFiles(Optional ByVal start As Int32 = 0, Optional ByVal length As Int32 = -1)
Dim last As Int32 = If(length < 0, Me.Files.Count - 1, start + length - 1)
For fileNr As Int32 = start To last
Dim fullPath As String = Me.LocalDirectory & "\" & Me.Files(fileNr).Name
If IO.File.Exists(fullPath) Then IO.File.Delete(fullPath)
Next
End Sub
Private Sub calculateFilesSize()
fireEventFromBgw([Event].CalculationFileSizesStarted)
m_totalSize = 0
For fileNr As Int32 = 0 To Me.Files.Count - 1
bgwDownloader.ReportProgress(InvokeType.CalculatingFileNrRaiser, fileNr + 1)
Try
Dim webReq As HttpWebRequest = CType(Net.WebRequest.Create(Me.Files(fileNr).Path), HttpWebRequest)
Dim webResp As HttpWebResponse = CType(webReq.GetResponse, HttpWebResponse)
m_totalSize += webResp.ContentLength
webResp.Close()
Catch ex As Exception
End Try
Next
fireEventFromBgw([Event].FileSizesCalculationComplete)
End Sub
Private Sub downloadFile(ByVal fileNr As Int32)
m_currentFileSize = 0
fireEventFromBgw([Event].FileDownloadAttempting)
Dim file As FileInfo = Me.Files(fileNr)
Dim size As Int64 = 0
Dim readBytes(Me.PackageSize - 1) As Byte
Dim currentPackageSize As Int32
Dim writer As New FileStream(Me.LocalDirectory & "\" & file.Name, IO.FileMode.Create)
Dim speedTimer As New Stopwatch
Dim readings As Int32 = 0
Dim exc As Exception
Dim webReq As HttpWebRequest
Dim webResp As HttpWebResponse
Try
webReq = CType(Net.WebRequest.Create(Me.Files(fileNr).Path), HttpWebRequest)
webResp = CType(webReq.GetResponse, HttpWebResponse)
size = webResp.ContentLength
Catch ex As Exception
exc = ex
End Try
m_currentFileSize = size
fireEventFromBgw([Event].FileDownloadStarted)
If exc IsNot Nothing Then
bgwDownloader.ReportProgress(InvokeType.FileDownloadFailedRaiser, exc)
Else
m_currentFileProgress = 0
While m_currentFileProgress < size
If bgwDownloader.CancellationPending Then
speedTimer.Stop()
writer.Close()
webResp.Close()
Exit Sub
End If
trigger.WaitOne()
speedTimer.Start()
currentPackageSize = webResp.GetResponseStream().Read(readBytes, 0, Me.PackageSize)
m_currentFileProgress += currentPackageSize
m_totalProgress += currentPackageSize
fireEventFromBgw([Event].ProgressChanged)
writer.Write(readBytes, 0, currentPackageSize)
readings += 1
If readings >= Me.StopWatchCyclesAmount Then
m_currentSpeed = CInt(Me.PackageSize * StopWatchCyclesAmount * 1000 / (speedTimer.ElapsedMilliseconds + 1))
speedTimer.Reset()
readings = 0
End If
End While
speedTimer.Stop()
writer.Close()
webResp.Close()
fireEventFromBgw([Event].FileDownloadSucceeded)
End If
fireEventFromBgw([Event].FileDownloadStopped)
End Sub
Private Sub bgwDownloader_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgwDownloader.RunWorkerCompleted
Me.IsPaused = False
m_busy = False
If Me.HasBeenCanceled Then
RaiseEvent Canceled(Me, New EventArgs)
Else
RaiseEvent Completed(Me, New EventArgs)
End If
RaiseEvent Stopped(Me, New EventArgs)
RaiseEvent IsBusyChanged(Me, New EventArgs)
RaiseEvent StateChanged(Me, New EventArgs)
End Sub
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not m_disposed Then
If disposing Then
' Free other state (managed objects)
bgwDownloader.Dispose()
End If
' Free your own state (unmanaged objects)
' Set large fields to null
Me.Files = Nothing
End If
m_disposed = True
End Sub
#End Region
#Region "Properties"
''' <summary>Gets or sets the list of files to download</summary>
Public Property Files() As List(Of FileInfo)
Get
Return m_files
End Get
Set(ByVal value As List(Of FileInfo))
If Me.IsBusy Then
Throw New InvalidOperationException("You can not change the file list during the download")
Else
If Me.Files IsNot value Then m_files = value
End If
End Set
End Property
''' <summary>Gets or sets the local directory in which files will be stored</summary>
Public Property LocalDirectory() As String
Get
Return m_localDirectory
End Get
Set(ByVal value As String)
If value <> Me.LocalDirectory Then
m_localDirectory = value
End If
End Set
End Property
''' <summary>Gets or sets if the FileDownloader should support total progress statistics. Note that when enabled, the FileDownloader will have to get the size of each file before starting to download them, which can delay the
operation.</summary>
Public Property SupportsProgress() As Boolean
Get
Return m_supportsProgress
End Get
Set(ByVal value As Boolean)
If Me.IsBusy Then
Throw New InvalidOperationException("You can not change the SupportsProgress property during the download")
Else
m_supportsProgress = value
End If
End Set
End Property
''' <summary>Gets or sets if when the download process is cancelled the complete downloads should be deleted</summary>
Public Property DeleteCompletedFilesAfterCancel() As Boolean
Get
Return m_deleteCompletedFiles
End Get
Set(ByVal value As Boolean)
m_deleteCompletedFiles = value
End Set
End Property
''' <summary>Gets or sets the size of the blocks that will be downloaded</summary>
Public Property PackageSize() As Int32
Get
Return m_packageSize
End Get
Set(ByVal value As Int32)
If value > 0 Then
m_packageSize = value
Else
Throw New InvalidOperationException("The PackageSize needs to be greather then 0")
End If
End Set
End Property
''' <summary>Gets or sets the amount of blocks that need to be downloaded before the progress speed is re-calculated. Note: setting this to a low value might decrease the accuracy</summary>
Public Property StopWatchCyclesAmount() As Int32
Get
Return m_stopWatchCycles
End Get
Set(ByVal value As Int32)
If value > 0 Then
m_stopWatchCycles = value
Else
Throw New InvalidOperationException("The StopWatchCyclesAmount needs to be greather then 0")
End If
End Set
End Property
''' <summary>Gets or sets the busy state of the FileDownloader</summary>
Public Property IsBusy() As Boolean
Get
Return m_busy
End Get
Set(ByVal value As Boolean)
If Me.IsBusy <> value Then
m_busy = value
m_canceled = Not value
If Me.IsBusy Then
m_totalProgress = 0
bgwDownloader.RunWorkerAsync()
RaiseEvent Started(Me, New EventArgs)
RaiseEvent IsBusyChanged(Me, New EventArgs)
RaiseEvent StateChanged(Me, New EventArgs)
Else
m_paused = False
bgwDownloader.CancelAsync()
RaiseEvent CancelRequested(Me, New EventArgs)
RaiseEvent StateChanged(Me, New EventArgs)
End If
End If
End Set
End Property
''' <summary>Gets or sets the pause state of the FileDownloader</summary>
Public Property IsPaused() As Boolean
Get
Return m_paused
End Get
Set(ByVal value As Boolean)
If Me.IsBusy Then
If value <> Me.IsPaused Then
m_paused = value
If Me.IsPaused Then
trigger.Reset()
RaiseEvent Paused(Me, New EventArgs)
Else
trigger.Set()
RaiseEvent Resumed(Me, New EventArgs)
End If
RaiseEvent IsPausedChanged(Me, New EventArgs)
RaiseEvent StateChanged(Me, New EventArgs)
End If
End If
End Set
End Property
''' <summary>Gets if the FileDownloader can start</summary>
Public ReadOnly Property CanStart() As Boolean
Get
Return Not Me.IsBusy
End Get
End Property
''' <summary>Gets if the FileDownloader can pause</summary>
Public ReadOnly Property CanPause() As Boolean
Get
Return Me.IsBusy And Not Me.IsPaused And Not bgwDownloader.CancellationPending
End Get
End Property
''' <summary>Gets if the FileDownloader can resume</summary>
Public ReadOnly Property CanResume() As Boolean
Get
Return Me.IsBusy And Me.IsPaused And Not bgwDownloader.CancellationPending
End Get
End Property
''' <summary>Gets if the FileDownloader can stop</summary>
Public ReadOnly Property CanStop() As Boolean
Get
Return Me.IsBusy And Not bgwDownloader.CancellationPending
End Get
End Property
''' <summary>Gets the total size of all files together. Only avaible when the FileDownloader suports progress</summary>
Public ReadOnly Property TotalSize() As Int64
Get
If Me.SupportsProgress Then
Return m_totalSize
Else
Throw New InvalidOperationException("This FileDownloader that it doesn't support progress. Modify SupportsProgress to state that it does support progress to get the total size.")
End If
End Get
End Property
''' <summary>Gets the total amount of bytes downloaded</summary>
Public ReadOnly Property TotalProgress() As Int64
Get
Return m_totalProgress
End Get
End Property
''' <summary>Gets the amount of bytes downloaded of the current file</summary>
Public ReadOnly Property CurrentFileProgress() As Int64
Get
Return m_currentFileProgress
End Get
End Property
''' <summary>Gets the total download percentage. Only avaible when the FileDownloader suports progress</summary>
Public ReadOnly Property TotalPercentage(Optional ByVal decimals As Int32 = 0) As Double
Get
If Me.SupportsProgress Then
Return Math.Round(Me.TotalProgress / Me.TotalSize * 100, decimals)
Else
Throw New InvalidOperationException("This FileDownloader that it doesn't support progress. Modify SupportsProgress to state that it does support progress.")
End If
End Get
End Property
''' <summary>Gets the percentage of the current file progress</summary>
Public ReadOnly Property CurrentFilePercentage(Optional ByVal decimals As Int32 = 0) As Double
Get
Return Math.Round(Me.CurrentFileProgress / Me.CurrentFileSize * 100, decimals)
End Get
End Property
''' <summary>Gets the current download speed in bytes</summary>
Public ReadOnly Property DownloadSpeed() As Int32
Get
Return m_currentSpeed
End Get
End Property
''' <summary>Gets the FileInfo object representing the current file</summary>
Public ReadOnly Property CurrentFile() As FileInfo
Get
Return Me.Files(m_fileNr)
End Get
End Property
''' <summary>Gets the size of the current file in bytes</summary>
Public ReadOnly Property CurrentFileSize() As Int64
Get
Return m_currentFileSize
End Get
End Property
''' <summary>Gets if the last download was canceled by the user</summary>
Private ReadOnly Property HasBeenCanceled() As Boolean
Get
Return m_canceled
End Get
End Property
#End Region
End Class
#End Region
End Namespace
< b>下载按钮</b>
<b>THE DOWNLOAD BUTTON</b>
< b> LISTVIEW复选框CLIXCK</b>
<b>LISTVIEW CHECKBOX CLIXCK</b>
推荐答案
您好,学术举措-学习资源"论坛的主题是与在线/离线培训/学习资源相关的帖子微软的学术计划.
Hello, The 'Academic Initiatives - Learning Resources' forum is for posts related to online / offline training / learning resources as related to Microsoft's Academic Initiatives.
我要在中询问 MSDN上的Visual Basic .Net 语言论坛.
I'd ask in the Visual Basic .Net Language forum on MSDN.
卡尔
这篇关于如何下载文件...帮助的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!