祝愿大家身体健康!

 站点注册  找回密码
 站点注册

QQ登录

只需一步,快速开始

查看: 82|回复: 0

[PBIDEA] PBIDEA:用 uo_httpclient 做大文件下载并显示实时进度

[复制链接]

[PBIDEA] PBIDEA:用 uo_httpclient 做大文件下载并显示实时进度

[复制链接]
pbai

主题

0

回帖

1032

积分

PBAI

积分
1032
贡献
在线时间
小时
7 小时前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?站点注册

×
PBIDEA:用 uo_httpclient 做大文件下载并显示实时进度

阅读说明
1. 适用版本:PBIDEA 1.x(基于 PB 12.5 运行库;uo_httpclient 由 PbIdea.dll 提供,需安装 PBIDEA 运行库)。本文示例依赖 PBIDEA 运行库,经典 PB(未装 PBIDEA)无此对象。
2. 支持数据库:不涉及数据库(本文为 HTTP 文件下载,与 DBMS 无关,故不罗列)。
3. 操作系统与环境要求:Windows 7+,已安装 PBIDEA 运行库(PbIdea.dll 等);工程中需导入含 uo_httpclient 的 pbl(websuite.pbl)。
4. 难度系数:★★★☆☆
5. 其它阅读说明:建议先了解 Day4《uo_httpclient 发请求》的 GET/POST 基础;进度示例需在窗口上放置进度条控件 p_1 与多行编辑框 mle_1(仅进度示例需要,基础下载示例不需要任何控件)。

一、核心概念与原理

在 PBIDEA 里做 HTTP 下载,主力对象是 uo_httpclient(位于 websuite.pbl,底层基于 Windows 的 WinHTTP)。它把"下载到磁盘"和"下载到内存"两套能力都封装好了,而且内置了进度回调事件,让我们在下载大文件时能把实时进度显示给用户,而不是卡在一个没有反馈的界面上。

下载这件事有两个最关键的落点:


  • 落盘还是落内存DownLoadFile(...) 直接把远程文件写到本机磁盘;DownLoad(...) 把内容读进 blob,由你自己决定怎么处理。大文件一般直接落盘,体积小或需要 Immediate 加工的内容才用 blob。
  • 同步 + 事件回调DownLoadFile / DownLoad 本身是同步调用——函数不返回就代表还没下完。但在下载过程中,它会周期性触发 ondownload 事件,把"总字节数 / 已下字节数 / 百分比 / 当前文件名"四个参数传进来;下载结束时再触发 onfinish 事件。也就是说,界面反馈靠事件,控制流靠同步返回


百分比参数 ai_percentinteger(0~100),两个字节数参数是 double(因为大文件字节数会超过 long 上限,用 double 兜底)。ondownload 返回 TRUE 表示继续下载,FALSE 表示中止下载——这正是"取消按钮"的实现入口。

二、uo_httpclient 下载相关 API 全貌

下载主题相关的接口、事件、常量清单如下(均来自 websuite.pbl/uo_httpclient.sru 真实导出):

下载函数(PbIdea.dll 原生)

  • boolean DownLoadFile(readonly string strUrl) —— 下载到当前目录下的 .\download\ 子目录(目录需存在)。
  • boolean DownLoadFile(readonly string strUrl, readonly string strSavePath) —— 下载并保存到指定完整路径(含文件名)。
  • boolean DownLoadFile(readonly string strUrl, readonly string strSavePath, boolean bTriggerEvent) —— 同上,第三个参数 TRUE 时才触发 ondownload / onfinish 事件。
  • blob DownLoad(readonly string strUrl) —— 下载到内存 blob(不落盘)。
  • blob DownLoad(readonly string strUrl, boolean bTriggerEvent) —— 同上,第二个参数控制是否触发进度事件。


下载相关事件

  • event type boolean ondownload(double ad_totalsize, double ad_downsize, integer ai_percent, string as_file) —— 进度回调,返回 TRUE 继续、FALSE 中止。
  • event onfinish(boolean success, string info) —— 下载结束回调,success 表示成败。


常用配套设置(下载前调用)

  • SetProxy(readonly string ip, int port) —— 设置代理。
  • SetTimeout(ulong nTimeout)SetTimeout(ulong nConn, ulong nSend, ulong nRecv) —— 超时(单位毫秒)。
  • SetBasicAuth(username, password) / SetJWTAuth(token) —— 鉴权(私有仓库 / 内网服务常用)。
  • SetHeader(key, value) / SetHeader(uo_map) —— 自定义请求头(例如带 token、设 Range)。


动作常量(Request 用,下载一般用不到但列出来备查)

  • HttpGet=1 HttpPost=2 HttpPut=3 HttpPatch=4 HttpDelete=5 ……HttpHead=7 等。

注意:uo_httpclientglobal uo_httpclient uo_httpclient(自动实例化全局变量),所以你也可以直接写 uo_httpclient.DownLoadFile(...)。但如果要写 ondownload 事件代码,必须新建一个继承自 uo_httpclient 的子类 NVO,把代码写在子类的事件里——全局自动实例无法挂自定义事件体。

三、典型用法示例

示例 1:最基础——直接下载落盘
前置:工程中已导入 websuite.pbl(含 uo_httpclient),运行环境已装 PBIDEA 运行库。无界面控件要求,可在按钮 clicked 或任意脚本处运行。
步骤:把下方代码贴入按钮 clicked 事件,运行并点击按钮,即可在 MessageBox 看到下载成败。
  1. // 示例输入:远程文件地址
  2. string ls_url
  3. ls_url = 'https://example.com/release/bigfile.zip'
  4. // 示例输入:本机保存的完整路径(目录必须已存在)
  5. string ls_save
  6. ls_save = 'C:\temp\bigfile.zip'
  7. // HTTP 客户端对象
  8. uo_httpclient hc
  9. hc = create uo_httpclient
  10. // 下载结果
  11. boolean lb_ok
  12. lb_ok = false
  13. // 两参重载:不触发进度事件,直接落盘
  14. lb_ok = hc.DownLoadFile(ls_url, ls_save)
  15. if lb_ok then
  16.     MessageBox('下载完成', '文件已保存到:' + ls_save)
  17. else
  18.     MessageBox('下载失败', '请检查 URL 是否可达、保存目录是否存在')
  19. end if
  20. destroy hc
复制代码

示例 2:带实时进度——用子类挂 ondownload 事件
前置:新建一个 NVO(如 uo_httpclient_prog)继承自 uo_httpclient,在其 ondownload 事件写进度刷新代码(见下方"事件体");窗口 w_demo 上放进度条控件 p_1 与多行编辑框 mle_1,并把 p_1minposition=0maxposition=100
步骤:1) 建子类并写事件体;2) 在窗口按钮 clicked 贴入"调用代码";3) 运行窗口点击按钮,即可看到进度条与文字实时刷新。

事件体(写在 uo_httpclient_prog 的 ondownload 事件中):事件四个入参为 ad_totalsize(总字节数,double)、ad_downsize(已下字节数,double)、ai_percent(百分比 0~100,integer)、as_file(当前文件名);返回 TRUE 继续下载、FALSE 中止。下面把进度刷新到窗口控件 p_1(进度条)与 mle_1(多行编辑框):
  1. p_1.position = ai_percent
  2. mle_1.text = '已下载 ' + String(ad_downsize) + ' / ' + String(ad_totalsize) + ' 字节(' + String(ai_percent) + '%)'
  3. return TRUE
复制代码

调用代码(窗口按钮 clicked 事件):
  1. // 示例输入:远程文件地址
  2. string ls_url
  3. ls_url = 'https://example.com/release/bigfile.zip'
  4. // 示例输入:本机保存的完整路径
  5. string ls_save
  6. ls_save = 'C:\temp\bigfile.zip'
  7. // 继承了 ondownload 事件的子类实例
  8. uo_httpclient_prog hc
  9. hc = create uo_httpclient_prog
  10. // 三参重载:第三个参数 TRUE 才会触发 ondownload / onfinish 事件
  11. hc.DownLoadFile(ls_url, ls_save, TRUE)
  12. // 走到这里下载已经结束(期间进度条已实时刷新)
  13. MessageBox('提示', '下载已结束,结束时会触发 onfinish 事件')
  14. destroy hc
复制代码

示例 3:下载到内存 blob 再落盘
前置:同示例 1,需 websuite.pbl 与 PBIDEA 运行库;本例额外用到 uo_file.BlobToFile(websuite.pbl,真实存在)把 blob 写盘。
步骤:把下方代码贴入按钮 clicked 事件,运行后可在 MessageBox 看到下载字节数。
  1. // 示例输入:远程文件地址(这里以下载一个 PDF 为例)
  2. string ls_url
  3. ls_url = 'https://example.com/docs/report.pdf'
  4. // 示例输入:本机保存路径
  5. string ls_save
  6. ls_save = 'C:\temp\report.pdf'
  7. // 内存中的文件内容
  8. blob lbl_data
  9. // HTTP 客户端对象
  10. uo_httpclient hc
  11. hc = create uo_httpclient
  12. // 文件工具对象(PBIDEA 自带,BlobToFile 真实存在)
  13. uo_file uf
  14. uf = create uo_file
  15. // 写盘结果
  16. boolean lb_ok
  17. lb_ok = false
  18. // 一参(URL)+ 二参(TRUE 触发进度事件):内容读进 blob,不落盘
  19. lbl_data = hc.DownLoad(ls_url, TRUE)
  20. if Len(lbl_data) > 0 then
  21.     // 把 blob 写成文件
  22.     lb_ok = uf.BlobToFile(lbl_data, ls_save)
  23.     MessageBox('下载完成', '字节数:' + String(Len(lbl_data)))
  24.     destroy uf
  25. else
  26.     MessageBox('下载失败', '返回内容为空,请检查 URL 与网络')
  27. end if
  28. destroy hc
复制代码

四、边界情况与易错点

易错点现象 / 后果正确处理
bTriggerEvent 没传 TRUE下载能成功,但 ondownload / onfinish 永不触发,进度条不动用三参 DownLoadFile(url, path, TRUE) 或两参 DownLoad(url, TRUE)
保存路径目录不存在DownLoadFile 返回 FALSE,文件没生成uo_dir / DirectoryExists 建好目录再下载
单参 DownLoadFile(url)落到当前目录 .\download\,路径不在你预期的位置明确传第二参完整路径,别依赖默认目录
在 UI 线程直接下载大文件函数同步阻塞,下载期间窗口"假死"、进度条不重绘把下载丢到 uo_thread 后台线程(见第六节),或至少提示用户不要操作
ondownload 返回 FALSE 忘了处理下载被中止却没提示,用户以为卡住onfinishsuccess 参数能反映是否成功,用它统一收尾
忘了 destroy hc每次下载都留一个 WinHTTP 句柄,长期运行句柄泄漏下载结束后 destroy hc(示例均已包含)
代理 / 超时没设内网下载超时无反馈、或走不通代理下载前调用 SetProxy / SetTimeout(毫秒)


额外提醒:两个字节数参数是 double,显示时用 String(...) 即可;百分比 ai_percentinteger,直接赋给进度条 position 就行,无需换算。

五、与其它下载方案对比

方案对象特点何时选
HTTP 下载(本文)uo_httpclient原生 WinHTTP,支持进度事件、代理、鉴权,最通用绝大多数从 http/https 拉文件
带进度对话框的下载器uo_downloader(继承 uo_curl自带 uo_progress 悬浮进度窗 + 异步消息(onfilestart/onprogressdown/onfileend),开箱即用想少写代码、要现成进度 UI
底层可定制下载uo_curluo_downloader 的父类,能力最全但需自己接事件需要 curl 级控制(断点、限速等)
FTP / SFTP 文件传输uo_ftp / uo_sftp走 FTP/SFTP 协议,不是 HTTP服务器只提供 FTP/SFTP 时


个人经验:如果只是"下一个文件并显示进度",uo_httpclient 三参 DownLoadFile + 子类事件已经足够;如果连进度对话框都不想自己画,uo_downloader.download(title, url, path) 一行搞定(它内部用 uo_progress 弹窗 + 异步消息,WaitAsyncMessageFinish 等下载完成)。但要记住 uo_downloader 底层是 uo_curl,与 uo_httpclient 不是同一个对象,不要混用 API。

六、进阶扩展

1. 后台下载,界面不卡(推荐做法)

DownLoadFile 是同步的,大文件会阻塞 UI 线程。把下载丢进 uo_thread 后台线程,主线程照常响应;进度通过线程安全的全局变量 / 消息回传主线程刷新进度条。要点:


  • 下载函数体放在一个 NVO 的方法里,用 uo_thread_factory.StartThread("uo_downloader_job", "of_download", ...) 启动;
  • 跨线程只传标量(url、路径、百分比),不要跨线程直接操作窗口控件;
  • 主线程用 Timer 或自定义消息定时读取"已下字节数"刷新进度条。


2. 取消下载

ondownload 事件里判断一个实例变量(如 ib_cancel),用户点"取消"按钮时把它置 TRUE,事件返回 FALSE 即可中止当前下载。

3. 带鉴权 / 自定义头

下载私有仓库或内网接口前,先 hc.SetBasicAuth('user','pass')hc.SetHeader('Authorization', 'Bearer ' + ls_token),再调 DownLoadFile。头要在下载函数之前设置好。

4. 关于断点续传

uo_httpclient 的公开 API 里没有暴露"断点续传 / Range 续传"接口。真要做续传,只能自己 SetHeader('Range', 'bytes=' + 已下字节 + '-') 并用 DownLoad 取剩余片段再拼接——但服务器是否支持 Range、PbIdea 是否透传该头都需要实测,不保证可用,生产环境慎用。需要稳定的断点续传,建议改用 uo_curl 体系或自己用 uo_file 分块读写实现。

小结uo_httpclient 做大文件下载的核心是"三参 DownLoadFile(url, path, TRUE) + 子类 ondownload 事件":事件给进度、同步给结果、返回 FALSE 给取消。记住设好保存目录、及时 destroy、大文件放后台线程,下载功能就稳了。
共享共进共赢
Sharing And Win-win Results
SYBASEBBS - 免责申明1、欢迎访问“SYBASEBBS.COM”,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@sybasebbs.com
您需要登录后才可以回帖 登录 | 站点注册

本版积分规则

免责声明:
本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:Admin@SybaseBbs.com

客服微信:18669893686
挂谷猜想 · 探索

QQ|Archiver|PowerBuilder(PB)BBS社区 ( 鲁ICP备2021027222号-1 )

GMT+8, 2026-8-27 14:46 , Processed in 0.020871 second(s), 9 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表