• VB.net webbrowser 自定义下载接口实现


     使用《VB.net webbrowser 如何实现自定义下载 IDownloadManager》中的控件ExtendedWebBrowser(下载控件),并扩展了NewWindow2。

    使用ExtendedWebBrowser_1过程中,遇到很多问题,花了几天时间,终于解决了所有问题。

    问题1:接管了下载后,发现大文件下载,主程序会阻塞。

            一开始,以为是在写文件时因为IO响应导致阻塞,改用异步写,等等...尝试,发现阻塞依然,看过《C# 用FileStream.WriteAsync 异步读文件,调用线程还是被阻塞了》等文章后,问题依然未能解决。

            最后尝试主程序不写文件(就是接管下载后,在OnDataAvailable中对接收数据不操作),不做任何操作,阻塞依然存在。阻塞会导致下载中断,而且这种情况与下载文件大小无关,即使很小几M的文件也会发生。

            苦思中,记起以前写一个延时函数时,为了不阻塞而加入了Application.DoEvents()语句,于是在最频繁操作的OnDataAvailable中加入Application.DoEvents()语句,问题终于得到完满解决。

    问题2:写文件

            一开始,是主程序写文件,遇到太多麻烦,在解决问题1中,发现接管了下载后,其实IE是有在后台进程中将文件下载到IE缓冲区的,OnProgress第一次便是返回IE缓冲区中下载的文件名,于是便改用:等下载完后从IE缓冲区复制文件。(貌似IE原有下载器也是这样干的?)

    问题3:对于会弹出新窗口的下载,在进行第二次下载时,没有触发下载。

            因为主程序中接管弹出窗口的Extendedwebbrowser_2一直没关闭(IE中下载窗口是立即关闭的),并且发现,在NewWindow2中将弹出下载转到Extendedwebbrowser_2触发下载时,Extendedwebbrowser_2并没有触发DocumentCompleted,估计就是这里导致第二次下载时不能触发。
           解决办法:在下载完后,Extendedwebbrowser_2加载空白页"about:blank",问题解决。
     

    下面是IWebBrowserDownloadManager接口完整代码:

    1. Imports Remotion.Dms.Clients.Windows.WebBrowserControl
    2. Imports System.IO
    3. Namespace MyDownloadmanager '定义接口,以实现接口引用 2023.10.27
    4. Public Class MyDownloadmanager
    5. Implements IWebBrowserDownloadManager
    6. Dim INetCacheFile As String
    7. '一些状态的判定(True、False),其中的一种状态(True或False)必须放在接口内进行设定,
    8. '不能全部都靠通过外部进程来设定,外部进程只进行其中一种状态的改变就好,否则因为轮询时间差而导致不同步引发非预期结果发生。
    9. '例如:AfterLoadBlank
    10. #Region "增加属性,将接口的数据传递出去以及传进来"
    11. #Region "可读写属性"
    12. Private _ContinueDownload As Boolean = True
    13. Public Property ContinueDownload() As Boolean
    14. Get
    15. Return _ContinueDownload
    16. End Get
    17. Set(ByVal value As Boolean)
    18. _ContinueDownload = value
    19. End Set
    20. End Property
    21. Private _DownloadDir As String = ""
    22. Public Property DownloadDir() As String
    23. Get
    24. Return _DownloadDir
    25. End Get
    26. Set(ByVal value As String)
    27. _DownloadDir = value
    28. End Set
    29. End Property
    30. Private _AttchmentFilename As String = ""
    31. Public Property AttchmentFilename() As String
    32. Get
    33. Return _AttchmentFilename
    34. End Get
    35. Set(ByVal value As String)
    36. _AttchmentFilename = value
    37. End Set
    38. End Property
    39. '对于会弹出新窗口的下载,因为程序中接管的webbrowser一直没关闭,
    40. ’在下载完后,需要加载一次新页(在这里加载空白页"about:blank"),
    41. ‘否则可能无法进行下一次下载。
    42. Private _AfterLoadBlank As Boolean = False
    43. Public Property AfterLoadBlank() As Boolean
    44. Get
    45. Return _AfterLoadBlank
    46. End Get
    47. Set(ByVal value As Boolean)
    48. _AfterLoadBlank = value
    49. End Set
    50. End Property
    51. #End Region
    52. #Region "ReadOnly Property"
    53. Dim _DownloadFileName As String = ""
    54. Public ReadOnly Property DownloadFileName() As String
    55. Get
    56. Return _DownloadFileName
    57. End Get
    58. End Property
    59. Private _totalSize As Integer
    60. Public ReadOnly Property GetTotalSize() As Integer
    61. Get
    62. Return _totalSize
    63. End Get
    64. End Property
    65. Private _currentValue As Integer
    66. Public ReadOnly Property GetCurrentValue() As Integer
    67. Get
    68. Return _currentValue
    69. End Get
    70. End Property
    71. Private _success As Boolean
    72. Public ReadOnly Property GetSuccess() As Boolean
    73. Get
    74. Return _success
    75. End Get
    76. End Property
    77. Private _statusText As String
    78. Public ReadOnly Property GetStatusText() As String
    79. Get
    80. Return _statusText
    81. End Get
    82. End Property
    83. Private _isAborted As Boolean
    84. Public ReadOnly Property GetisAborted() As Boolean
    85. Get
    86. Return _isAborted
    87. End Get
    88. End Property
    89. Private _IsDownloadCompleted As Boolean = False
    90. '下载开始时,设置为false,下载结束或退出时,设置为True
    91. Public ReadOnly Property IsDownloadCompleted() As Boolean
    92. Get
    93. Return _IsDownloadCompleted
    94. End Get
    95. End Property
    96. Private _OnStartDownloading As Boolean = False
    97. '下载开始时,设置为false,下载结束或退出时,设置为True
    98. Public ReadOnly Property OnStartDownloading() As Boolean
    99. Get
    100. Return _OnStartDownloading
    101. End Get
    102. End Property
    103. #End Region
    104. #End Region
    105. #Region "接口函数"
    106. Public Sub OnAborted() Implements Remotion.Dms.Clients.Windows.WebBrowserControl.IWebBrowserDownloadManager.OnAborted
    107. WriteRunLog("OnAborted")
    108. _isAborted = True
    109. _IsDownloadCompleted = True
    110. _OnStartDownloading = False
    111. End Sub
    112. Public Function OnDataAvailable(ByVal buffer() As Byte, ByVal bytesAvailable As Integer) As Boolean Implements Remotion.Dms.Clients.Windows.WebBrowserControl.IWebBrowserDownloadManager.OnDataAvailable
    113. _currentValue += bytesAvailable
    114. '需要加这行,否则可能下载时发生阻塞,导致下载中断,而且这种情况与下载文件大小无关,即使很小几M的文件也会发生。
    115. Application.DoEvents()
    116. Return _ContinueDownload
    117. End Function
    118. '在下载完后,需要加载一次新页(在这里加载空白页"about:blank"),否则可能无法进行下一次下载。
    119. Public Sub OnDownloadCompleted(ByVal success As Boolean, ByVal statusText As String) Implements Remotion.Dms.Clients.Windows.WebBrowserControl.IWebBrowserDownloadManager.OnDownloadCompleted
    120. _isAborted = False
    121. _IsDownloadCompleted = True
    122. _OnStartDownloading = False
    123. _AfterLoadBlank = True
    124. _success = success
    125. _statusText = statusText
    126. _AttchmentFilename = ""
    127. WriteRunLog("OnDownloadCompleted:" + success.ToString + " " + statusText)
    128. If success Then
    129. If String.IsNullOrEmpty(INetCacheFile) Then
    130. WriteRunLog("没有找到IE缓冲区文件!文件 " + _DownloadFileName + " 下载失败!")
    131. Else
    132. File.Copy(INetCacheFile, _DownloadFileName, overwrite:=True) '从IE缓冲区复制文件
    133. WriteRunLog("找到IE缓冲区文件: " + INetCacheFile + ",复制到:" + _DownloadFileName)
    134. End If
    135. End If
    136. End Sub
    137. Public Function OnProgress(ByVal currentValue As Integer, ByVal totalSize As Integer, ByVal statusText As String) As Boolean Implements Remotion.Dms.Clients.Windows.WebBrowserControl.IWebBrowserDownloadManager.OnProgress
    138. _totalSize = totalSize
    139. '从第一次OnProgress中获取下载文件名
    140. If String.IsNullOrEmpty(_DownloadFileName) Then
    141. _DownloadFileName = MyGetFileName(statusText)
    142. If String.IsNullOrEmpty(_DownloadFileName) Then
    143. _DownloadFileName = "TmpFile"
    144. End If
    145. If Directory.Exists(_DownloadDir) Then
    146. _DownloadFileName = _DownloadDir + "\" + _DownloadFileName
    147. End If
    148. End If
    149. If String.IsNullOrEmpty(INetCacheFile) Then
    150. If InStr(statusText, "Windows\INetCache") > 0 Then '查找IE缓冲区文件 保存路径、文件名
    151. INetCacheFile = statusText
    152. 'WriteRunLog("OnProgress找到IE缓冲区文件: " + INetCacheFile)
    153. End If
    154. End If
    155. System.Windows.Forms.Application.DoEvents()
    156. Return _ContinueDownload
    157. End Function
    158. Public Function OnStartDownload(ByVal uri As System.Uri) As Boolean Implements Remotion.Dms.Clients.Windows.WebBrowserControl.IWebBrowserDownloadManager.OnStartDownload
    159. _currentValue = 0
    160. _OnStartDownloading = True
    161. _ContinueDownload = True
    162. _IsDownloadCompleted = False
    163. INetCacheFile = ""
    164. _DownloadFileName = ""
    165. WriteRunLog("OnStartDownload :" + uri.ToString)
    166. Return True
    167. End Function
    168. 'OnStartDownload:http://115.1.115.15:9080/FrntMonitor/servlet/com.icbc.cte.cs.servlet.CSReqServlet
    169. '1、第一次获得文件名 OnProgress:0 totalSize:0 statusText: C:\Users\gdzs-liyh\AppData\Local\Microsoft\Windows\Temporary Internet Files\Content.IE5\0F2VEW6C\statatmdev[2].xls
    170. '2、第二次获得下载链接 OnProgress:3483 totalSize:0 statusText:(OnStartDownload中的网址:http://115.1.115.15:9080/FrntMonitor/servlet/com.icbc.cte.cs.servlet.CSReqServlet)
    171. '3483就是在这时候读取的数据大小。
    172. 'OnProgress:3483 totalSize:0 statusText: C:\Users\gdzs-liyh\AppData\Local\Microsoft\Windows\Temporary Internet Files\Content.IE5\0F2VEW6C\statatmdev[2].xls
    173. 'OnDataAvailable:38281 (这个就是文件的实际大小)(可能文件小,此时文件已经下载到缓存:C:\Users\gdzs-liyh\AppData\Local\Microsoft\Windows\Temporary Internet Files\Content.IE5\0F2VEW6C\statatmdev[2].xls)
    174. 'OnProgress:38281 totalSize:0 statusText:(OnStartDownload中的网址)
    175. 'OnDownloadCompleted
    176. '=================================
    177. 'OnStartDownload :http://115.96.14.11/kjbbs/UpLoadFile/2010-7/20107214401523292.doc
    178. '1、第一次获得文件名 OnProgress:0 totalSize:0 statusText :http://115.96.14.11/kjbbs/UpLoadFile/2010-7/20107214401523292.doc
    179. '2、第二次获得下载链接 OnProgress:119296 totalSize:119296 statusText :http://115.96.14.11/kjbbs/UpLoadFile/2010-7/20107214401523292.doc
    180. 'OnProgress:119296 totalSize:119296 statusText :C:\Users\gdzs-liyh\AppData\Local\Microsoft\Windows\Temporary Internet Files\Content.IE5\5Q44G40U\20107214401523292.doc
    181. 'OnProgress:119296 totalSize:119296 statusText :http://115.96.14.11/kjbbs/UpLoadFile/2010-7/20107214401523292.doc
    182. 'OnDataAvailable:119296 (可能文件小,此时文件已经下载到缓存:C:\Users\gdzs-liyh\AppData\Local\Microsoft\Windows\Temporary Internet Files\Content.IE5\0F2VEW6C\statatmdev[2].xls)
    183. 'OnDownloadCompleted
    184. #End Region
    185. Shared Sub WriteRunLog(ByVal MyMsg As String)
    186. 'Using w As StreamWriter = File.AppendText("RunLog.txt")
    187. Dim w As StreamWriter
    188. If File.Exists("RunLog.txt") Then
    189. If My.Computer.FileSystem.GetFileInfo("RunLog.txt").Length > 10485760 Then '2017.5.4 文件大于10M,清0
    190. w = File.CreateText("RunLog.txt")
    191. w.Write("文件大于10M,置0从头开始!")
    192. w.Write(Chr(9))
    193. Else
    194. w = File.AppendText("RunLog.txt")
    195. End If
    196. Else
    197. w = File.CreateText("RunLog.txt")
    198. End If
    199. w.Write(Now)
    200. w.Write(Chr(9)) '插入Tab键
    201. w.WriteLine(MyMsg)
    202. w.Flush()
    203. w.Close()
    204. 'End Using
    205. End Sub
    206. Public Function MyGetFileName(ByVal inStr As String) As String
    207. '获取文件名, '文件夹名、文件名不能包含下列字符\/:*?"<>|
    208. Dim ss As String
    209. ss = System.IO.Path.GetFileName(inStr)
    210. Dim n = InStrRev(ss, "=")
    211. If n < ss.Length Then
    212. ss = ss.Substring(n)
    213. End If
    214. MyGetFileName = ss.Replace("\", "").Replace("/", "").Replace(":", "").Replace("*", "").Replace("?", "").Replace(Chr(34), "").Replace("<", "").Replace(">", "").Replace("|", "")
    215. If InStrRev(MyGetFileName, "[") > 1 And InStrRev(MyGetFileName, "[") < InStrRev(MyGetFileName, "]") Then '将 21018102002617385797[1] 中的 [1] 去掉
    216. MyGetFileName = Left(MyGetFileName, InStrRev(MyGetFileName, "[") - 1) + Mid(MyGetFileName, InStrRev(MyGetFileName, "]") + 1)
    217. End If
    218. MyGetFileName = _AttchmentFilename + MyGetFileName
    219. End Function
    220. End Class
    221. End Namespace

  • 相关阅读:
    阿里巴巴对裁员谣言报警
    Ubuntu 24.04 抢先体验换国内源 清华源 阿里源 中科大源 163源
    Sa-Token 整合Java17和SpringBoot
    Linux 解压报错
    Gitlab-Runner安装并注册
    FastJson反序列化漏洞(复现)
    没有公网ip怎么做外网访问内网端口?快解析内网穿透
    如何基于surging架设流媒体视频推流(视频讲解)
    YOLOv5分类任务——手势识别
    DevSecOps基本概念介绍
  • 原文地址:https://blog.csdn.net/zslefour/article/details/134439084