C++ 将progressbar添加到wininet http upload C++;

C++ 将progressbar添加到wininet http upload C++;,c++,winapi,wininet,C++,Winapi,Wininet,我有在HTTP服务器上使用POST方法上载二进制文件的代码: http_upload_file(PCHAR szServer, PCHAR szScript, PCHAR szParam, PCHAR szValue, PCHAR szFile) { PCHAR szHeaders = "Content-Type: multipart/form-data; boundary=----qwerty"; PCHAR szData = "------qwerty\r\n"

我有在HTTP服务器上使用POST方法上载二进制文件的代码:

http_upload_file(PCHAR szServer, PCHAR szScript, PCHAR szParam, PCHAR szValue, PCHAR szFile)
{
    PCHAR szHeaders = "Content-Type: multipart/form-data; boundary=----qwerty";
    PCHAR szData    = "------qwerty\r\n"
                      "Content-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n"
                      "------qwerty\r\n"
                      "Content-Disposition: form-data; name=\"files[]\"; filename=\"%s\"\r\n"
                      "Content-Type: application/octet-stream\r\n"
                      "Content-Transfer-Encoding: binary\r\n\r\n";
    PCHAR szDataEnd = "\r\n------qwerty--\r\n";
    char  szHeader[512];

    HINTERNET hSession, hConnect, hRequest;
    DWORD     dwFileSize, dwBytesRead, dwContentLength,dwBytesWritten;

    hSession = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);

    if (hSession)
    {
        hConnect = InternetConnect(hSession, szServer, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP,0, 0);

        if (hConnect)
        {
            hRequest = HttpOpenRequest(hConnect, "POST", szScript, NULL, NULL, 0, 0, 0);

            if (hRequest)
            {
                HANDLE hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);

                if (hFile != INVALID_HANDLE_VALUE)
                {
                    dwFileSize      = GetFileSize(hFile, NULL);
                    wsprintf(szHeader, szData, szParam, szValue, szFile);
                    dwContentLength = lstrlen(szHeader) + dwFileSize + lstrlen(szDataEnd);
                    LPBYTE pBuf     = (LPBYTE)malloc(dwContentLength);
                    CopyMemory(&pBuf[0], szHeader, lstrlen(szHeader));
                    ReadFile(hFile, &pBuf[lstrlen(szHeader)], dwFileSize, &dwBytesRead, NULL);
                    CopyMemory(&pBuf[lstrlen(szHeader) + dwFileSize], szDataEnd, lstrlen(szDataEnd));
                    HttpSendRequest(hRequest, szHeaders, lstrlen(szHeaders), pBuf, dwContentLength);
                    CloseHandle(hFile);
                    free(pBuf);
                }
            }

            InternetCloseHandle(hRequest);
        }

        InternetCloseHandle(hConnect);
    }

    InternetCloseHandle(hSession);
}
它的工作很好,但我想添加一些程序信息,而文件上传

当HttpSendRequest(hRequest、szHeaders、lstrlen(szHeaders)、pBuf、dwContentLength)时,我可以获取传输内容的大小吗正在执行吗?问题是,当上传大文件时,我的
表单
被冻结,用户无法查看已经上传了多少数据。因此,我想添加
ProggessBar
以显示数据传输的大小,但不知道如何获取此传输数据


我很乐意接受任何建议。

您可以将上传内容分成小块,并在发送每一块后更新进度条

像往常一样调用
InternetConnect()
HttpOpenRequest()

而不是调用
HttpSendRequest()。通过
lpBuffersIn
参数定义总文件大小。对于参数
dwFlags
传递值
HSR\u INITIATE
,告知API您需要迭代数据传输。参考页中存在文档错误,
dwFlags
参数为保留。例如,每个人都在使用它

调用一个循环,将文件分块上传。使用不太小的缓冲区大小来减少API的开销(比如16k)。每次调用此API后,您可以测量当前时间和上次进度条更新时间之间的差异,并且只有在差异足够大(例如1/10秒)时才更新进度条,以减少更新GUI的API开销

上传完文件后,通过调用API告诉它。当然,关闭手柄,检查错误等

所有这些都应该在单独的线程中完成,以保持GUI线程的响应性。通过调用消息ID为
WM\u APP+x
PostMessage()
将进度报告给GUI线程。您可以使用
wParam
lParam
传递进度信息。然后,只有在GUI线程中,您才能实际更新进度条,以保持业务逻辑和GUI清楚地分开

INTERNET_BUFFERS buffer{ sizeof(buffer) };
buffer.dwBufferTotal = totalFileSizeInBytes;
BOOL success = HttpSendRequestEx( hRequest, &buffer, nullptr, HSR_INITIATE, 0 );