如何使用 WinInet 时提供下载上载进度信息
概要
许多开发人员都使用 WinInet 函数来下载或上载文件在 Internet 上的想要提供一个进度条以指示多少文件传输已完成,但多少就越长。您可以使用以下机制来完成此。
Collapse image更多信息
使用 InternetSetStatusCallback 来获取下载进度的通知为您提供良好的信息请求的进展如何,包括连接状态通知。但是,它不表示一定百分比的传输已完成。
若要获取的百分比相当完整的通知,您需要确定传输的大小,然后使用小缓冲区中调用 InternetReadFile 或 InternetWriteFile。然后,您可以作为完整的函数调用来计算传输的百分比。
例如,假设您想要下载的 1000 个字节的文件。而不是进行一次调用 InternetReadFile 1000 字节的缓冲区,可以拨打 10 InternetReadFIle 与 100 字节的缓冲区。通过这种方式完成每次调用 InternetReadFile,您知道下载是另一个完整的 10%。
下面的代码说明了此过程:
#include<windows.h>
#include<wininet.h>
#include<iostream.h> void main(int argc, char *argv[])
{
if (argc != 3)
{
cout << "Usage: progress <host> <object>" << endl;
return;
} HINTERNET hSession = InternetOpen("WinInet Progress Sample",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,
NULL,
0);
HINTERNET hConnection = InternetConnect(hSession,
argv[1], // Server
INTERNET_DEFAULT_HTTP_PORT,
NULL, // Username
NULL, // Password
INTERNET_SERVICE_HTTP,
0, // Synchronous
NULL); // No Context HINTERNET hRequest = HttpOpenRequest(hConnection,
"GET",
argv[2],
NULL, // Default HTTP Version
NULL, // No Referer
(const char**)"*/*\0", // Accept
// anything
0, // Flags
NULL); // No Context
HttpSendRequest(hRequest,
NULL, // No extra headers
0, // Header length
NULL, // No Body
0); // Body length DWORD dwContentLen;
DWORD dwBufLen = sizeof(dwContentLen);
if (HttpQueryInfo(hRequest,
HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
(LPVOID)&dwContentLen,
&dwBufLen,
0))
{
// You have a content length so you can calculate percent complete
char *pData = (char*)GlobalAlloc(GMEM_FIXED, dwContentLen + 1);
DWORD dwReadSize = dwContentLen / 10; // We will read 10% of data
// with each read. cout << "Download Progress:" << endl;
cout << " 0----------100%" << endl;
cout << " ";
cout.flush(); DWORD cReadCount;
DWORD dwBytesRead;
char *pCopyPtr = pData;
for (cReadCount = 0; cReadCount < 10; cReadCount++)
{
InternetReadFile(hRequest, pCopyPtr, dwReadSize, &dwBytesRead);
cout << "*";
cout.flush();
pCopyPtr = pCopyPtr + dwBytesRead;
}
// extra read to account for integer division round off
InternetReadFile(hRequest,
pCopyPtr,
dwContentLen - (pCopyPtr - pData),
&dwBytesRead);
// Null terminate data
pData[dwContentLen] = 0; // Display
cout << endl << "Download Complete" << endl;
cout << pData;
}
else
{
DWORD err = GetLastError();
// No content length...impossible to calculate % complete
// Just read until we are done.
char pData[100];
DWORD dwBytesRead = 1;
while (dwBytesRead)
{
InternetReadFile(hRequest, pData, 99, &dwBytesRead);
pData[dwBytesRead] = 0;
cout << pData;
}
}
}
有几点需要注意的使用这种方法时:
在开始之前,您必须知道的数据大小。上面的代码将尝试通过阅读使用 HttpQueryInfo 函数的 HTTP 内容长度标头来确定数据大小。尽管许多 HTTP 响应中包括的内容长度标头,则不需要。除非您有另一种机制,用于获取数据的大小,您将不能计算进度,如果在响应中未包括的内容长度标头。
如果您试图上载或下载 FTP 资源中,您将不能使用 FtpPutFile 或 FtpGetFile,并希望确定进度信息。您应该使用 FtpOpenFile,然后使用 InternetReadFile 和 InternetWriteFile,如上面所述。
因为提供进度的信息假定您必须知道数据的大小,可以使用 FtpGetFileSize 来下载文件之前获取 FTP 资源的大小。请注意 FtpGetFileSize 并不总是成功由于多种 FTP 服务器返回目录列表信息的方式获取的文件大小。有关使用 FTP 来获取目录列表信息的问题的其他信息,请参阅下面 Microsoft 知识库中相应的文章:
172712信息: 限制的 WinInet FTP 功能
如何使用 WinInet 时提供下载上载进度信息的更多相关文章
- 使用 new XMLHttpRequest() 制作下载文件进度条
mui 进度控件使用方法: 检查当前容器(container控件)自身是否包含.mui-progressbar类: 当前容器包含.mui-progressbar类,则以当前容器为目标控件,直接显示进度 ...
- Android动画之仿美团加载数据等待时,小人奔跑进度动画对话框(附顺丰快递员奔跑效果)
Android动画之仿美团加载数据等待时,小人奔跑进度动画对话框(附顺丰快递员奔跑效果) 首句依然是那句老话,你懂得! finddreams :(http://blog.csdn.net/finddr ...
- RDIFramework.NET平台代码生成器V3.0版本全新发布-更新于20160518(提供下载)
最新版本请转到:RDIFramework.NET平台代码生成器V3.1版本全新发布-更新于2016-10-08(提供下载) RDIFramework.NET代码生成器V3.0版本修改了针对3.0版本的 ...
- Word 打包 zip 并提供下载
该篇博客记录Java Web项目将word打包zip并提供下载功能的实现和其中遇到的坑,方便后续自己的查看的参照. 1. 后台处理的java 方法 首先将所有的word生成到uploadword目录下 ...
- RDIFramework.NET平台代码生成器V2.8发布-更新于2014-12-31(提供下载)
RDIFramework.NET平台代码生成器V2.8发布 更新于2014-12-31 注:已经发布了新版本,请转新版本下载: RDIFramework.NET平台代码生成器V3.0版本全新发布-更 ...
- Retrofit2文件上传下载及其进度显示
序 前面一篇文章介绍了Retrofit2的基本使用,这篇文章接着介绍使用Retrofit2实现文件上传和文件下载,以及上传下载过程中如何实现进度的显示. 文件上传 定义接口 1 2 3 @Multip ...
- ftp下载显示进度
经常用到ftp get命令下载东西,但是遇到大的文件不知道是挂了还是在运行,要是能显示就好了,于是就有了下文... 注: 红色 字体是我敲击的命令 “#” 是注释语 [root@localhost s ...
- RDIFramework.NET平台代码生成器V1.0发布(提供下载)
RDIFramework.NET平台代码生成器V1.0发布(提供下载) RDIFramework.NET(.NET快速开发整合框架)框架做为信息化系统快速开发.整合的框架,其目的一至是给用户和开发 ...
- Android OkHttp文件上传与下载的进度监听扩展
http://www.loongwind.com/archives/290.html 上一篇文章介绍了用Retrofit实现文件的上传与下载,但是我们发现没办法监听上传下载的进度,毕竟我们在做开发的时 ...
随机推荐
- Java位运算符
& 两个二进制数的相同位比较,都为1,结果为1,否则结果为0. | 两个二进制数的相同位比较,只要有一个为1,结果就为1,否则为0. ~ 对一个二进制数的每一位取反,原值为1,取反为0,原值为 ...
- windows系统调用 临界区机制
#include "iostream" #include "windows.h" #include "cstring" using name ...
- IOC 控制反转模式
1.依赖 依赖就是有联系,有地方使用到它就是有依赖它,一个系统不可能完全避免依赖。如果你的一个类或者模块在项目中没有用到它,恭喜你,可以从项目中剔除它或者排除它了,因为没有一个地方会依赖它。下面看一个 ...
- 转:客制FORM调用会计科目弹性域/根据科目取得CODE_COMBINATION_ID
1.首先在创建数据表时,添一个字段用来保存会计科目的ID.如:CODE_COMBINATION_ID 2.在FORM相应的数据块增加两个ITEM,用来显示科目NUMBER与DESCRITION. 例: ...
- Thinking in UML-1-为什么需要UML
1 从面向过程到面向对象 面向过程认为我们的世界是由一个个相互关联的小系统组成.逻辑严密.环环相扣.井然有序.但是我们这个世界从来不是一成不变的.世界的复杂性和频繁变革不是面向过程可以轻易应付应付的. ...
- [CrunchBang]修改win+ubuntu 双 系统菜单的 启动顺序 引导
说到启动就不得不说GRUB,Linux下大名鼎鼎的启动管理工具(曾经的LILO已经风光不再),当然现在已经是GRUB2了,GRUB2和GRUB最重要的区别就是,GRUB存放系统启动信息的文件为/boo ...
- 关于OpenGL的性能方面的技巧(不时更新)
显示列表可以有效提高渲染性能渲染顺序顶点层次分配内存管理递归查找 在有引擎的情况下,同一个模型对象会使用同一份内存和显存 优化裁剪算法,去掉无需渲染的对象 纹理阴影比体阴影效率要高 尽量使用UVW贴图 ...
- The method setCharacterEncoding(String) is undefined for the type HttpServletResponse 是什么原因?
response.setCharacterEncoding("gb2312"); 在Servlet2.3中是不行的,至少要2.4版本才可以,如果低于2.4版本,可以用如下办法: r ...
- Lost Cows(线段树 POJ2182)
Lost Cows Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10354 Accepted: 6631 Descriptio ...
- Android 编译时注解解析框架
2.注解 说道注解,竟然还有各种分类,得,这记不住,我们从注解的作用来反推其分类,帮助大家记忆,然后举例强化大家的记忆,话说注解的作用: 1.标记一些信息,这么说可能太抽象,那么我说,你见过@Over ...