Board logo

标题: 控制台下载工具pget.exe [打印本页]

作者: happy886rr    时间: 2017-4-19 23:49     标题: 控制台下载工具pget.exe

本帖最后由 happy886rr 于 2017-4-21 21:40 编辑
控制台下载工具pget,支持IP显示、彩显、通配符、断电续传、下载进度、速度、剩余时间提示等功能。假如我要下载的网址,某个地方不确定,用通配符(*)替代就行 http://www.a.com/(*).zip。
(图片为外链)
将该图存为a.zip,解压即可得到1.2版的二进制文件和所有源码,仅13KB大小,运行迅捷。

用法:
  1. -----------------------------------------------------------------
  2. pget -u[url] -n[number range] -r[root directory]
  3. -----------------------------------------------------------------
  4.      -h Show help information
  5.      -u Set the download url
  6.      -n Set the number range of the url
  7.      -r Set the download root directory
  8. -----------------------------------------------------------------
复制代码
举例:
  1. REM 单文件下载,使用-u开关指定下载地址
  2. pget -uhttp://ddd2.pc6.com/soft12/VC6.0green.rar
  3. REM 通配符下载,使用-n开关指定统配符范围
  4. pget -u http://img1.mm131.com/pic/1008/(*).jpg -n 1-10
  5. REM 用-r开关指定文件保存目录
  6. pget -u http://img1.mm131.com/pic/1008/(*).jpg -n 1-10 -r ".\test"
复制代码
pget最新1.3版源码,加入了对ftp、百度网盘超长链接下载的支持,1.3版仅做源码更新,不再提供新的二进制文件,且源码支持VC6.0直接编译。
  1. /*
  2. THE BATCH DOWNLOAD TOOL, COPYRIGHT@2017~2019 BY HAPPY, VERSION 1.3
  3. PGET.EXE
  4. -----------------------------------------------------------------
  5.                _
  6.    _       _ _(_)_     |  The Batch Download Tool with colorful ,
  7.   (_)     | (_) (_)    |  Copyright@2017~2019 By Happy, Pget.Exe
  8.    _ _   _| |_  __ _   |  Type "-h" for help.
  9.   | | | | | | |/ _` |  |  
  10.   | | |_| | | | (_| |  |  Version 1.3 (2017-04-21 21:28 UTC)
  11. _/ |\__'_|_|_|\__'_|  |  Official http://www.bathome.net/thread
  12. |__/                   |  -43879-1-1.html
  13. -----------------------------------------------------------------
  14.                       :;vLxLc;,                  
  15.                   ,JZMMBBBMBMBMBJi.               
  16.                 LRBMMRMRRDWZZKRMBMBDs            
  17.               rBMBWDDDKKPE00XZPHEGORRMu           
  18.             .ZBRODOG0XZZGZGKZKPaEHGEEKRD         
  19.            ,OBOROGZGZE0DZEZZ0ZPDKXZWK0SEE         
  20.           .EBORWGZDZKKDEGKGGEPWGZZWEZaEJB;        
  21.           UBRRDDGRWOOMRREOOOKOEGXKHWKPP2ZH        
  22.          7BRWGOGBMBMBMBBBMBMBRORWPPEO0ZPRO        
  23.          RMOEWOBRPr;:,:ruxc3x7DBMBOMRRGWMX        
  24.         ;MMEOOBP.  :SRBU:     ,iDOBBRRWWB:        
  25.         vBMGWBG.     .;ii:. .::::raGRRGBE         
  26.         :MBZMBJ         .,..;;PMOL,2BBBD.         
  27.          UMRRBx  . ..,.,.. ,:..,::7BMBZ.         
  28.           MRMMM ...:;..,;,:;:..  ,BMBK.           
  29.           0BMBR;...::;::;;;;,,..sBBB7            
  30.          :BRBi,i7:.  .:;r;:...;OBOJ               
  31.         ;BMBr ::i7;,.......sF                     
  32.     LGBBBMBMF:;,:;777i;;:1BMBRr                  
  33.   iBMBMBMMRBO7::.:ic7c77;aBBMBBBMBMBEZv:,:.      
  34. :BMZFHWMORRMOr...:icvvr;:KMBRRDOOODRWD1cr7:.     
  35. SRuis0MRRRRRREL,..,::::,:EMORRMOROOuu1i:. :::.   
  36. ;3Ba7aBRZGBROMBWF: .....:;0ZRRMMBMBMB7::7L:  .;rL;
  37. ;;SOZBMOJ,3BRRBBMRc..,.,,:2RRMOMF7rXJ;;7LZOMi.....
  38. 7:;0BSMWx; 7RRRRBMBD:.,,,:DEMRWWMPL,:iL;ir1BBJ:.  
  39. :. sBxsMM3; :MOBMBDBG:.,.;UaBMOWMBM0:;v1uSvLLLrri:
  40. J;. KWsLBMU:aMBMBMcLGx...:7JBMMWMU2H  .,rKR0J;;;r;
  41. JL7  .  iBDRMBMBO: .7x,..,;7MBMBRU 1J:       ....
  42. siJ7.:s1RMBRPcr:     ,:,::;.iRBMBMUGBMBOs:    . .
  43. :;rJUcJsrLL.           :;r,  .rZMMMBK0DBMBMu.   .
  44. ..7vJur7ir:  ::.        :.     :s;:r1L: .7BMBB3:  
  45. . :vs3rx;L. ...,        .,      .i:  .:.:r;;;DMBBM
  46. , .,727;,,.,:....                 ,::...3JLr   .JG
  47. . .,;U7;..:i;::;,..  .             :ir:rxu1v.     
  48. : ,.:xJ:..:;7iL3i.;:  ...      ..   :;1JLL07, ..,.
  49. : . .;v7ir:;;rvcr::7                 7ciLSU7.
  50. */
  51. #include   <stdio.h>
  52. #include  <stdlib.h>
  53. #include  <string.h>
  54. #include <windows.h>
  55. #include  <direct.h>
  56. #include    <time.h>
  57. #include    <math.h>
  58. #include      <io.h>
  59. #pragma comment(lib, "Ws2_32.lib")
  60. /*************宏量定义*************/
  61. #define SAFE_SIZE  1024
  62. #define FILE_EXIST 0
  63. //定义帮助说明
  64. #define HELP_INFORMATION "\
  65. -----------------------------------------------------------------\n\
  66. pget -u[url] -n[number range] -r[root directory]\n\
  67. -----------------------------------------------------------------\n\
  68.      -h Show help information\n\
  69.      -u Set the download url\n\
  70.      -n Set the number range of the url\n\
  71.      -r Set the download root directory\n\
  72. -----------------------------------------------------------------\n\
  73. version 1.3\n"
  74. #define STR_HEAD "\
  75. -------------Welcome you to use the pget download tool-----------"
  76. #define STR_LINE "\
  77. -----------------------------------------------------------------"
  78. /*************类型定义*************/
  79. typedef HRESULT (WINAPI *PGETA)(LPUNKNOWN,LPCSTR,LPCSTR,DWORD,LPBINDSTATUSCALLBACK);
  80. /*************全局变量*************/
  81. static int M, N, Z;
  82. static char murl[SAFE_SIZE], mpath[SAFE_SIZE]=".\\";
  83. static char proGRESS[64]={0};
  84. int OPTIND=1, OPTOPT;
  85. char* OPTARG;
  86. clock_t preTime;
  87. ULONG preProgress;
  88. HANDLE handle_out;
  89. /*************进度回调*************/
  90. class DownloadProgress :public IBindStatusCallback
  91. {
  92. public:
  93. HRESULT __stdcall QueryInterface(const IID &, void **) {
  94. return E_NOINTERFACE;
  95. }
  96. ULONG STDMETHODCALLTYPE AddRef(void) {
  97. return 1;
  98. }
  99. ULONG STDMETHODCALLTYPE Release(void) {
  100. return 1;
  101. }
  102. HRESULT STDMETHODCALLTYPE OnStartBinding(DWORD dwReserved, IBinding *pib) {
  103. return E_NOTIMPL;
  104. }
  105. virtual HRESULT STDMETHODCALLTYPE GetPriority(LONG *pnPriority) {
  106. return E_NOTIMPL;
  107. }
  108. virtual HRESULT STDMETHODCALLTYPE OnLowResource(DWORD reserved) {
  109. return S_OK;
  110. }
  111. virtual HRESULT STDMETHODCALLTYPE OnStopBinding(HRESULT hresult, LPCWSTR szError) {
  112. return E_NOTIMPL;
  113. }
  114. virtual HRESULT STDMETHODCALLTYPE GetBindInfo(DWORD *grfBINDF, BINDINFO *pbindinfo) {
  115. return E_NOTIMPL;
  116. }
  117. virtual HRESULT STDMETHODCALLTYPE OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed) {
  118. return E_NOTIMPL;
  119. }
  120. virtual HRESULT STDMETHODCALLTYPE OnObjectAvailable(REFIID riid, IUnknown *punk) {
  121. return E_NOTIMPL;
  122. }
  123. virtual HRESULT __stdcall OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText){
  124. if (ulProgressMax != 0){
  125. //进度百分数
  126. int downloadSpeed, restTime;
  127. int i=(int)ulProgress * 100.0 / (int)ulProgressMax;
  128. int j=i/2, disTime=(int)(clock()-preTime);
  129. if(disTime > 100){
  130. downloadSpeed=((int)ulProgress-(int)preProgress) * CLOCKS_PER_SEC / disTime / 1000;
  131. restTime=(downloadSpeed!=0) ?((int)ulProgressMax-(int)ulProgress) / downloadSpeed :99999;
  132. preProgress=ulProgress, preTime+=disTime;
  133. }else if(i <100){
  134. return S_OK;
  135. }
  136. if(i==100){
  137. downloadSpeed=restTime=0;
  138. }
  139. for(int n=1; n<=j; n++){
  140. proGRESS[n]='=';
  141. }
  142. //显示进度百分比
  143. fprintf(stdout, "\r%s%3d%% %3dKB/s,%3dm%02ds ", proGRESS, i, downloadSpeed, restTime/1000/60, restTime/1000%60);
  144. fflush(stdout);
  145. }
  146. return S_OK;
  147. }
  148. };
  149. /*************功能函数*************/
  150. //彩显函数
  151. int ColorString(HANDLE handle_out, char* pstrA, char* pstrB, int colorA, int colorB, int num)
  152. {
  153. SetConsoleTextAttribute(handle_out, colorA);  //项目色
  154. fprintf(stdout, pstrA);
  155. SetConsoleTextAttribute(handle_out, colorB);  //数据色
  156. (num<0)?fprintf(stdout, pstrB):fprintf(stdout, "%d\n", num);
  157. return 0;
  158. }
  159. //判断字母
  160. BOOL isLetter(char* p)
  161. {
  162. return (p && (('A'<=*p&&*p<='Z')||('a'<=*p&&*p<='z'))&&(*(p+1)=='\0'))?TRUE:FALSE;
  163. }
  164. //子串查找/i版
  165. char* strrstr(const char *dst, const char *src)  
  166. {  
  167. const char *pdst=dst, *psrc=src;
  168. char *ret=NULL;  
  169. while(*dst){
  170. while(*pdst==*psrc){
  171. if(*pdst=='\0'){
  172. return ret=(char*)dst;
  173. }else{  
  174. pdst++;  
  175. psrc++;  
  176. }  
  177. }  
  178. if(*psrc=='\0'){ret=(char*)dst;}
  179. pdst=++dst;  
  180. psrc=src;  
  181. }  
  182. return ret;  
  183. }
  184. //域名IP解析
  185. int URLDownloadToIP(HANDLE handle_out, const char* downloadURL)
  186. {
  187. WSADATA wsaData;  
  188. WSAStartup(MAKEWORD(2,2), &wsaData);
  189. char *pstr=(char*)downloadURL, *urlweb=(char*)calloc(SAFE_SIZE, sizeof(char)), *tstr=urlweb;
  190. while(*pstr!=':'){pstr++;}
  191. pstr+=3;
  192. while(*pstr!='/'&& *pstr!='\n' && *pstr!='\0'){
  193. *tstr++=*pstr++;
  194. }
  195. const char* pszUrl=(const char*)urlweb;
  196. if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
  197. //fprintf(stdout, "Init socket faile\n");  
  198. return 1;  
  199. }
  200. struct hostent *pHost = gethostbyname(pszUrl);
  201. if (pHost == NULL) {  
  202. WSACleanup();  
  203. //fprintf(stdout, "pHost == NULL \n");  
  204. return 1;  
  205. }
  206. //主机正式名称
  207. ColorString(handle_out, "[URL-HOST] ", (pHost)?pHost->h_name:"NULL", 4|8, 1|2|8, -1);
  208. fprintf(stdout, "\n");
  209. //主机别名,可以有多个
  210. int iIndex = 0;  
  211. while(pHost->h_aliases[iIndex]) {
  212. ColorString(handle_out, "[URLALIAS] ", pHost->h_aliases[iIndex], 4|8, 1|2|8, -1);
  213. fprintf(stdout, "\n");
  214. iIndex++;  
  215. }
  216. //地址字节数,IPV4是4,IPV6是6
  217. if(pHost->h_length==4) {
  218. ColorString(handle_out, "[IP-VTYPE] ", "IPV4\n", 4|8, 4|8, -1);
  219. }
  220. else if(pHost->h_length==6) {
  221. ColorString(handle_out, "[IP-VTYPE] ", "IPV6\n", 4|8, 4|8, -1);
  222. }
  223. iIndex = 0;
  224. while(pHost->h_addr_list[iIndex]) {
  225. ColorString(handle_out, "[IP-ADDRE] ", inet_ntoa(*(struct in_addr*)pHost->h_addr_list[iIndex]), 4|8, 2|4|8, -1);
  226. fprintf(stdout, "\n");
  227. iIndex++;  
  228. }   
  229. WSACleanup();
  230. //释放空间
  231. free(urlweb);
  232. return 0;
  233. }
  234. //开关解析
  235. int GetOpt(int nargc, char *nargv[], char *ostr)
  236. {
  237. static char* place="";
  238. static char* lastostr=(char *) 0;
  239. register char* oli;
  240. char* index();
  241. if(ostr!=lastostr){
  242. lastostr=ostr;
  243. place="";
  244. }
  245. if(!*place){
  246. if(
  247. (OPTIND>=nargc)              ||
  248. (*(place=nargv[OPTIND])!='-')||
  249. (!*(++place))
  250. ){
  251. place="";
  252. return(EOF);
  253. }
  254. if (*place == '-' && place[1] == 0){
  255. ++OPTIND;
  256. return(EOF);
  257. }
  258. }
  259. if ((OPTOPT=(int)*place++)==(int)':' || !(oli=strchr(ostr, OPTOPT))){
  260. if(!*place){++OPTIND;}
  261. }
  262. if (oli != NULL && *(++oli) != ':'){
  263. OPTARG=NULL;
  264. if(!*place){++OPTIND;}
  265. }
  266. else{
  267. if(*place){
  268. OPTARG=place;
  269. }else if(nargc<=++OPTIND){
  270. place="";
  271. }else{
  272. OPTARG=nargv[OPTIND];
  273. }
  274. place="";
  275. ++OPTIND;
  276. }
  277. return(OPTOPT);
  278. }
  279. /*************下载函数*************/
  280. int URLGetToFile(void)
  281. {
  282. //装载DLL模块
  283. HMODULE hLib=LoadLibraryW(L"URLMON");
  284. if(hLib==NULL){
  285. fprintf(stdout, "ERROR");
  286. return 1;
  287. }
  288. //过小红伞本地查杀
  289. PGETA PgetUrlToFileA=(PGETA)GetProcAddress(hLib, "URLDownloadToFileA");
  290. //是否启用通配符
  291. BOOL useMARK=FALSE;
  292. //分配URL字串
  293. char* aurl =(char*)calloc(SAFE_SIZE, sizeof(char));
  294. char* durl =(char*)calloc(SAFE_SIZE, sizeof(char));
  295. char* dest =(char*)calloc(SAFE_SIZE, sizeof(char));
  296. char* pftr =(char*)calloc(       16, sizeof(char));
  297. //定义URL指针
  298. char *purl=NULL, *surl=NULL, *pdit=NULL;
  299. //批量下载
  300. for(int i=M; i<=N; i++){
  301.     surl=murl, purl=aurl;
  302. while(*surl !='\0'){
  303. //替换正则标签
  304. if(*surl=='(' && *(surl+1)=='*' && *(surl+2)==')'){
  305. useMARK=TRUE;
  306. if(Z >0){
  307. sprintf(pftr, "%%0%dd", Z);
  308. sprintf(dest, pftr, i);
  309. }else if(Z==-1){
  310. sprintf(dest, "%c",  (char)i);
  311. }else{
  312. sprintf(dest, "%d",  i);
  313. }
  314. pdit=dest;
  315. while(*pdit !='\0'){
  316. *(purl++)=*(pdit++);
  317. }
  318. surl+=3;
  319. }else{
  320. *(purl++)=*(surl++);
  321. }
  322. }
  323. //置结束符
  324. *purl='\0';
  325. strcpy(durl, mpath);
  326. strcat(durl, "\\");
  327. strcat(durl, strrchr(aurl, '/')+1);
  328. //截断特殊字符
  329. purl=durl;
  330. while(
  331. *purl!='?' &&
  332. *purl!='*' &&
  333. *purl!='"' &&
  334. *purl!='>' &&
  335. *purl!='<' &&
  336. *purl!='|' &&
  337. *purl!='\0'
  338. ){purl++;}
  339. *purl='\0';
  340. //显示下载网址
  341. ColorString(handle_out, "[*] ", aurl, 4|8, 1|2|8, -1);
  342. fprintf(stdout, "\n");
  343. //绘制进度框
  344. ColorString(handle_out, "", (char*)proGRESS, 4|8, 2|4|8, -1);
  345. //进度归零
  346. memset(proGRESS, ' ', 51);
  347. proGRESS[0]='[', proGRESS[51]=']';
  348. preTime=clock();
  349. preProgress=(ULONG)0;
  350. //进度回调入口
  351. DownloadProgress progress;
  352. IBindStatusCallback* callback=(IBindStatusCallback*)&progress;
  353. //调用API下载
  354. if (PgetUrlToFileA(NULL, aurl, durl, 0, static_cast<IBindStatusCallback*>(&progress)) != S_OK){
  355. fprintf(stdout, "ERROR");
  356. }
  357. //统一换行
  358. fputs("\n\n", stdout);
  359. if(useMARK==FALSE){
  360. break;
  361. }
  362. }
  363. //清理工作
  364. free(aurl);
  365. free(durl);
  366. free(dest);
  367. free(pftr);
  368. return 0;
  369. }
  370. /*************MAIN函数*************/
  371. int main(int argc, char** argv)
  372. {
  373. if(argc<2){
  374. //无参数则退出
  375. fprintf(stdout, HELP_INFORMATION);
  376. exit(0);
  377. }
  378. int flag=0, K;
  379. while((K=GetOpt(argc,argv,"hu:n:r:"))!=-1)
  380. {
  381. switch(K)
  382. {
  383. case 'h':
  384. case 'H':
  385. fprintf(stdout, HELP_INFORMATION);
  386. exit(0);
  387. case 'u':
  388. case 'U':
  389. if(OPTARG !=NULL){
  390. strcpy(murl, OPTARG);
  391. flag=1;
  392. }
  393. break;
  394. case 'n':
  395. case 'N':
  396. if(OPTARG !=NULL){
  397. char *snumsrc=strtok(OPTARG, " \t-"), *tmps=(snumsrc!=NULL)?strtok(NULL, " \t-"):NULL, *zp=snumsrc;
  398. if(isLetter(snumsrc) && isLetter(tmps)){
  399. int exnum1=*snumsrc, exnum2=*tmps;
  400. Z=-1;
  401. M=(exnum1 <= exnum2)?(N=exnum2, exnum1):(N=exnum1, exnum2);
  402. }else if(tmps!=NULL){
  403. if(*zp=='0'){
  404. while('0'<= *zp && *zp <='9'){
  405. Z++;
  406. zp++;
  407. }
  408. }
  409. M=atoi(snumsrc), N=atoi(tmps);
  410. if(M>N){
  411. int exnum=M;
  412. M=N, N=exnum;
  413. }
  414. }
  415. }
  416. break;
  417. case 'r':
  418. case 'R':
  419. if(OPTARG !=NULL){
  420. strcpy(mpath, OPTARG);
  421. }
  422. break;
  423. default:
  424. fprintf(stdout, "Unknown switch '-%c'\n", K);
  425. exit(1);
  426. }
  427. }
  428. //判断是否有网址参数
  429. if(flag==0){
  430. fprintf(stdout, "Needs download url\n");
  431. exit(1);
  432. }
  433. //判断网址是否超长
  434. if(strlen(murl)>768){
  435. fprintf(stdout, "Download url too long\n");
  436. exit(1);
  437. }
  438. //判断网址是否有效
  439. if(
  440. (strrchr((const char*)murl, '/')==NULL) ||
  441. (
  442. (strrstr((const char*)murl, "http://" ) != murl) &&
  443. (strrstr((const char*)murl, "https://") != murl) &&
  444. (strrstr((const char*)murl, "ftp://"  ) != murl) &&
  445. (strrstr((const char*)murl, "ftps://" ) != murl)
  446. )
  447. ){
  448. fprintf(stdout, "The url is error\n");
  449. exit(1);
  450. }
  451. //下载目录不否存则创建
  452. if(_access(mpath, FILE_EXIST)!=0){
  453. _mkdir(mpath);
  454. }
  455. //无法创建下载目录退出
  456. if(_access(mpath, FILE_EXIST)!=0){
  457. fprintf(stdout, "Can not creat the download directory\n");
  458. exit(1);
  459. }
  460. //获取控制台输出句柄
  461. handle_out=GetStdHandle(STD_OUTPUT_HANDLE);
  462. //获取控制台初始配色
  463. WORD orgCOLOR;
  464. CONSOLE_SCREEN_BUFFER_INFO buffINFO;
  465. GetConsoleScreenBufferInfo(handle_out, &buffINFO);
  466. orgCOLOR=buffINFO.wAttributes;
  467. //显示目标网站IP
  468. ColorString(handle_out, STR_HEAD, "\n", 4|8, 2|4|8, -1);
  469. URLDownloadToIP(handle_out, murl);
  470. ColorString(handle_out, STR_LINE, "\n", 4|8, 2|4|8, -1);
  471. //调用下载函数
  472. URLGetToFile();
  473. //还原字体颜色
  474. SetConsoleTextAttribute(handle_out, orgCOLOR);
  475. return 0;
  476. }
复制代码

作者: freesoft00    时间: 2017-4-20 00:29

这个是否支持https连接下载,是否支持设置代((理
作者: happy886rr    时间: 2017-4-20 00:39

回复 2# freesoft00
理论上都支持,我刚测试过,支持https,代理自己写上ip端口试试。
作者: CrLf    时间: 2017-4-20 11:45

传一个备份,回头上传到 Batch-CN
已用 strip 和 upx 压缩体积,另,HELP_INFORMATION 的末尾应该有个 \n 才对
作者: CrLf    时间: 2017-4-20 12:14

毕竟是在 windows 下使用,建议以后的作品考虑一下适配宽字符的情况
作者: happy886rr    时间: 2017-4-20 13:20

回复 5# CrLf
好的,不过url一般都是ascii码组成的,ansi C已经够用。
作者: 523066680    时间: 2017-4-20 14:22

回复 6# happy886rr


    是啊,一般连中文都会变成 UTF8的URL编制形式(%e4%b8%ad)
作者: CrLf    时间: 2017-4-20 20:32

卧槽,怎么编译到这么小的
作者: happy886rr    时间: 2017-4-20 20:46

本帖最后由 happy886rr 于 2017-4-20 20:50 编辑

回复 8# CrLf
MD版,只要安装了QQ,就带那个dll,所以直接MD版 。第一版getopt的开关也写错了,1.1版都做了修正。
作者: CrLf    时间: 2017-4-20 22:44

回复 9# happy886rr


    目前直接运行看到的提示最后一行是两行黏在一起的,建议下次更新时在 version 后补个 \n
作者: happy886rr    时间: 2017-4-20 23:09

本帖最后由 happy886rr 于 2017-4-21 13:45 编辑

回复 10# CrLf
好的,已过360免杀,模仿hash.c。




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