Board logo

标题: [原创] vbs“多线程”下载 [打印本页]

作者: wankoilz    时间: 2013-4-30 00:11     标题: vbs“多线程”下载

本帖最后由 wankoilz 于 2013-5-12 11:46 编辑

昨天重新看了下《深入挖掘Windows脚本技术》(原文不知道是谁写的,网上到处都是)。
里面提到了vbs多线程下载,今天尝试写了一下。
话说还是闲来练手,初步实现了自己认为的“多线程”下载。(注意这里的引号,关于vbs与多线程请参考12楼链接)
为避免冗余,省了一些错误检查。我觉得没多大实际用途,有兴趣的兄弟一起学习讨论呗。欢迎大家指正:
  1. 'From bbs.bathome.net By wankoilz
  2. url=InputBox("输入完整下载地址:")
  3. threadCount=InputBox("输入线程数(不超过10吧,太多就累赘了):")
  4. fileName=GetFileName(url)
  5. filePath=GetFilePath(WScript.ScriptFullName)
  6. Set ohttp=CreateObject("msxml2.serverxmlhttp")
  7. Set ado=CreateObject("adodb.stream")
  8. Set fso=CreateObject("scripting.filesystemobject")
  9. ado.Type=1
  10. ado.Mode=3
  11. ado.Open
  12. ohttp.open "Head",url,True
  13. ohttp.send
  14. Do While ohttp.readyState<>4
  15.     WScript.Sleep 200
  16. Loop
  17. '获得文件大小
  18. fileSize=ohttp.getResponseHeader("Content-Length")
  19. ohttp.abort
  20. '创建一个和下载文件同样大小的临时文件,供下面ado分段重写
  21. fso.CreateTextFile(filePath&"TmpFile",True,False).Write(Space(fileSize))
  22. ado.LoadFromFile(filePath&"TmpFile")
  23. blockSize=Fix(fileSize/threadCount):remainderSize=fileSize-threadCount*blockSize
  24. upbound=threadCount-1
  25. '定义包含msxml2.xmlhttp对象的数组,·成员数量便是“线程”数
  26. '直接 Dim 数组名(变量名) 是不行的,这里用Execute变通了一下
  27. Execute("Dim arrHttp("&upbound&")")
  28. For i=0 To UBound(arrHttp)
  29.     startpos=i*blockSize
  30.     endpos=(i+1)*blockSize-1
  31.     If i=UBound(arrHttp) Then endpos=endpos+remainderSize
  32.     Set arrHttp(i)=CreateObject("msxml2.xmlhttp")
  33.     arrHttp(i).open "Get",url,True
  34.     '分段下载
  35.     arrHttp(i).setRequestHeader "Range","bytes="&startpos&"-"&endpos
  36.     arrHttp(i).send
  37. Next
  38. Do
  39.     WScript.Sleep 200
  40.     For i=0 To UBound(arrHttp)
  41.         If arrHttp(i).readystate=4 Then
  42.             '每当一个“线程”下载完毕就将其写入临时文件的相应位置
  43.             ado.Position=i*blockSize
  44.             MsgBox "线程"&i&"下载完毕!"
  45.             ado.Write arrHttp(i).responseBody
  46.             arrHttp(i).abort
  47.             complete=complete+1
  48.         End If
  49.     Next
  50.     If complete=UBound(arrHttp)+1 Then Exit Do
  51.     timeout=timeout+1
  52.     If timeout=5*30 Then
  53.         '根据文件大小设定
  54.         MsgBox "30秒超时!"
  55.         WScript.Quit
  56.     End If
  57. Loop
  58. If fso.FileExists(filePath&fileName) Then fso.DeleteFile(filePath&fileName)
  59. fso.DeleteFile(filePath&"TmpFile")
  60. ado.SaveToFile(filePath&fileName)
  61. MsgBox "文件下载完毕!"
  62. Function GetFileName(url)
  63.     arrTmp=Split(url,"/")
  64.     GetFileName=arrTmp(UBound(arrTmp))
  65. End Function
  66. Function GetFilePath(fullname)
  67.     arrTmp=Split(fullname,"\")
  68.     For i=0 To UBound(arrTmp)-1
  69.         GetFilePath=GetFilePath&arrTmp(i)&"\"
  70.     Next
  71. End Function
复制代码
测试下载地址:
  1. http://bbs.bathome.net/images/default/logo.gif
复制代码

作者: CrLf    时间: 2013-4-30 04:20

见过一种是用 ExcuteGlobal 创建全局过程来实现的,也很巧妙:
http://tieba.baidu.com/p/1011138043
作者: czjt1234    时间: 2013-4-30 10:41

2楼的,是同时启动多个vbs下载多个文件
应该是多进程
作者: Demon    时间: 2013-4-30 12:05

《深入挖掘Windows脚本技术》是zzzevazzz写的

原文地址http://www.xfocus.net/articles/200411/752.html

作者博客http://hi.baidu.com/zzzevazzz/item/f694350395a9608a02ce1ba9
作者: CrLf    时间: 2013-4-30 13:03

回复 3# czjt1234


    我贴的那个链接确实是多线程啊
    多进程方案貌似不在本贴讨论范围内
作者: Demon    时间: 2013-4-30 13:39

简单看了一下代码,姑且不论异步请求是否真的是多线程,假设它是多线程好了,

问题在于楼主用的是同步请求,里面的“线程”是按照顺序执行的,根本没有多线程的效果。
作者: Demon    时间: 2013-4-30 13:41

回复  czjt1234


    我贴的那个链接确实是多线程啊
    多进程方案貌似不在本贴讨论范围内
CrLf 发表于 2013-4-30 13:03


如何证明是多线程?
作者: CrLf    时间: 2013-4-30 14:10

本帖最后由 CrLf 于 2013-4-30 14:11 编辑

回复 7# Demon


    那个贴子里的代码关键部分有一句 "Get",url,True,赤果果的异步传输,至于能不能把异步传输和多线程简单对应起来,这就不晓得了,反正我是没观察到新进程产生,所以认为它是多线程。
    本贴嘛,没注意楼主用的是同步传输,但是看到 arrHttp(i).xxxx 的用法,大概思路也知道了,改成异步应该也是可行的吧?
作者: wankoilz    时间: 2013-4-30 15:08

搞错了,我一直还以为false是异步,糗了……
作者: wankoilz    时间: 2013-4-30 15:15

本帖最后由 wankoilz 于 2013-5-1 22:07 编辑

感谢指正,现在只能用手机,空了再改一下。
我认为同时发送多个下载请求,几个对象一起接收数据,这勉强能算是“多线程下载”吧。

已改正!
作者: CrLf    时间: 2013-4-30 15:19

回复 9# wankoilz


    看来楼主是不经常在单位或者学校干坏事的好孩子 ←_←
作者: Demon    时间: 2013-4-30 16:17

http://demon.tw/programming/vbs-multi-thread.html
作者: powerbat    时间: 2013-4-30 19:29

隐约记得ActiveX控件都是单线程模型?
作者: Demon    时间: 2013-4-30 20:28

隐约记得ActiveX控件都是单线程模型?
powerbat 发表于 2013-4-30 19:29


COM有4种线程模型

ThreadingModel="Both" indicates that instances of the class can execute in either an MTA or an STA.

ThreadingModel="Free" indicates that instances of the class can execute only in an MTA.

ThreadingModel="Apartment" indicates that instances of the class can execute only in an STA.

ThreadingModel="Absent" implies that instances of the class can run only in the main STA or the first STA initialized in the process.
作者: czjt1234    时间: 2013-5-1 08:38

4楼的链接,2004年的

厉害啊
作者: wuhengsi    时间: 2013-5-2 21:46

看到这个NB的技术很高兴
不过也感到很悲哀,,,复制到粘贴板就被杀软拦截。。。报毒。。。
难以使用应用起来。。。。。
早年的文件下载代码也是如此。。。。
作者: zqz0012005    时间: 2013-5-7 22:28

1、异步和多线程是不能划等号的,类似的还有中断、信号/消息等。

2、zzzevazzz的《深入挖掘Windows脚本技术》可谓曲高和寡,诞生到现在快10年,但个人感觉本论坛中能完全理解的应该不超过10人;初学者剪刀+胶水,一般人学到利用ie,高级的学到加密,能学到后面事件消费者的算得上大师了。




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2