Click to See Complete Forum and Search --> : WinInet API + "POST" request - how to make upload progress bar?


choxnox
July 22nd, 2007, 06:26 AM
Hi,

I'm using WinInet APIs in async mode to upload files to server using HTTP protocol and "POST" request. As a matter of fact, I'm trying to simulate HTML form (multipart data) submit button.

I can successfully send file, but I have problem with making progress bar while uploading.
Here is code I'm using for sending:

while (dwReadLength != 0)
{
DWORD dwBytesSent = 0;
dwReadLength = fileLocal.Read(pBuffer, dwChunkLength);

if (dwReadLength != 0)
{
if (!InternetWriteFile(hInternetFile, pBuffer, dwReadLength, &dwBytesWritten))
{
if (::GetLastError() != ERROR_IO_PENDING)
{
strError.Format("CFileHostingHttpUpload::UploadFile::InternetWriteFile(2) = %d",
::GetLastError());
return FALSE;
}
WaitForSingleObject(hAsyncOp, INFINITE);
}
dwTotalRead+=dwBytesWritten;

pbUpload->SetPos(((double)dwTotalRead/dwTotalRequestLength)*100);
}
}

The problem is that my progress bar gets fully "progressed" in about 1-2 seconds, but file uploading is far slower (25kb/s upload speed). When I track transfer with net sniffer tool I can see that it takes about 10 seconds to upload 256 kb file, but progress bar gets fill almost instantly. I've tried about 6-7 different upload "loops" but all of them are giving almost same result.

InternetStatusCallback gives me this:

11:49:19 - Connected to server.
11:49:19 - Sending request ...
11:49:19 - Request sent: 186 bytes
11:49:19 - Request complete.
11:49:19 - Sending request ...
11:49:19 - Request sent: 86 bytes
11:49:19 - Sending request ...
11:49:19 - Request sent: 4096 bytes
...
... (a lot of same status until the end of upload, no need to paste them all :))
...
11:49:19 - Sending request ...
11:49:19 - Request sent: 4096 bytes
11:49:19 - Sending request ...
11:49:19 - Request sent: 4096 bytes
11:49:19 - Request complete.
11:49:19 - Sending request ...
11:49:19 - Request sent: 802 bytes
11:49:19 - Sending request ...
11:49:19 - Request sent: 16 bytes
11:49:19 - Receiving response ...
11:49:29 - Response received: 1024 bytes
11:49:29 -
11:49:29 - Request complete.


Does anybody have any kind of solution?

Best Regards and have a nice day!

MikeAThon
July 22nd, 2007, 01:47 PM
Wait a sec: Is the code you posted inside your main GUI thread, or inside an independent worker thread?

If it's inside the main GUI thread, then the problem is that the code is in a tight loop, that doesn't permit processing of the WM_PAINT message being sent to the progress dialog.

Mike

choxnox
July 22nd, 2007, 03:38 PM
I've tried your advice to put whole WinInet thing in one separated (working) thread, but there's no difference. I don't think it's up to multithreading, because it's not only progress bar that does it's job "too earlier", for ex. I'm writing debug info to file and it's obvious that everything is done "too fast", it's even the same as if I set data block length from 4096 to 65k:

11:49:19 - Connected to server.
11:49:19 - Sending request ...
11:49:19 - Request sent: 186 bytes
11:49:19 - Request complete.
11:49:19 - Sending request ...
11:49:19 - Request sent: 86 bytes
11:49:19 - Sending request ...
11:49:19 - Request sent: 4096 bytes
...
... (a lot of same status until the end of upload, no need to paste them all :))
...
11:49:19 - Sending request ...
11:49:19 - Request sent: 4096 bytes
11:49:19 - Sending request ...
11:49:19 - Request sent: 4096 bytes
11:49:19 - Request complete.
11:49:19 - Sending request ...
11:49:19 - Request sent: 802 bytes
11:49:19 - Sending request ...
11:49:19 - Request sent: 16 bytes
11:49:19 - Receiving response ...
11:49:29 - Response received: 1024 bytes
11:49:29 -
11:49:29 - Request complete.


It doesn't make sense that InternetWriteFile write to file at speed of >2MB/s when my max. upload speed is 25kb/s, considering that request was made with flag INTERNET_FLAG_NO_CACHE_WRITE.

Like there is cache available somewhere ... strange.

MikeAThon
July 22nd, 2007, 04:32 PM
Your log file shows that the entire file is "sent" within a single second.

The only "cache" I am aware of is the internal send buffer in the winsock stack. That buffer works in kernel mode, and when programming on the basic winsock API, functions like send() complete when the data is accepted in the internal buffer, even though the data has not yet been transmitted onto the physicla wire. So maybe you are getting a completion signal every time the data is accepted in the internal winsock buffer.

I'm speculating, however, since I don't use the WinInet functions. Sorry I don't have more.

Mike