Updated downslib
- Added support for GZIP decompression - Increased chunk_size for the buffer to 8kb - Changed how header information is queried using HttpQueryInfoA using HTTP_QUERY_FLAG_NUMBER rather than copying it into the char buffer
This commit is contained in:
parent
4d725925d0
commit
8f06703061
|
|
@ -27,6 +27,10 @@ downslib_error downslib_download(const char* url,
|
|||
HINTERNET hInternet = nullptr;
|
||||
HINTERNET hUrl = nullptr;
|
||||
HANDLE hFile = nullptr;
|
||||
DWORD dwBufferSize = 0;
|
||||
const char* headers = nullptr;
|
||||
DWORD dwHeaderslen = 0;
|
||||
const DWORD chunk_size = 8192;
|
||||
|
||||
Cleanup cleanup([&]()
|
||||
{
|
||||
|
|
@ -51,6 +55,7 @@ downslib_error downslib_download(const char* url,
|
|||
SetLastError(dwLastError);
|
||||
});
|
||||
|
||||
// Create the PDB file that will be written to
|
||||
hFile = CreateFileW(filename, GENERIC_WRITE | FILE_READ_ATTRIBUTES, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if(hFile == INVALID_HANDLE_VALUE)
|
||||
return downslib_error::createfile;
|
||||
|
|
@ -64,57 +69,65 @@ downslib_error downslib_download(const char* url,
|
|||
if(!hInternet)
|
||||
return downslib_error::inetopen;
|
||||
|
||||
// Set a time-out value in milliseconds
|
||||
InternetSetOptionA(hInternet,
|
||||
INTERNET_OPTION_RECEIVE_TIMEOUT,
|
||||
&timeout,
|
||||
sizeof(timeout));
|
||||
|
||||
// Attempt to enable content decoding if the option is supported
|
||||
DWORD gzipDecoding = true;
|
||||
if (InternetSetOptionA(hInternet,
|
||||
INTERNET_OPTION_HTTP_DECODING,
|
||||
&gzipDecoding,
|
||||
sizeof(gzipDecoding))) {
|
||||
// Add the required request headers
|
||||
headers = "Accept-Encoding: gzip\r\n";
|
||||
dwHeaderslen = static_cast<DWORD>(strlen(headers));
|
||||
}
|
||||
|
||||
DWORD dwFlags = INTERNET_FLAG_RELOAD;
|
||||
if(strncmp(url, "https://", 8) == 0)
|
||||
dwFlags |= INTERNET_FLAG_SECURE;
|
||||
|
||||
hUrl = InternetOpenUrlA(hInternet, url, NULL, 0, dwFlags, 0);
|
||||
// Make the HTTP request
|
||||
hUrl = InternetOpenUrlA(hInternet, url, headers, dwHeaderslen, dwFlags, 0);
|
||||
if(!hUrl)
|
||||
return downslib_error::openurl;
|
||||
|
||||
// Get HTTP status code
|
||||
DWORD dwStatusCode;
|
||||
dwBufferSize = sizeof(dwStatusCode);
|
||||
if (HttpQueryInfoA(hUrl, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwStatusCode, &dwBufferSize, 0))
|
||||
{
|
||||
if (dwStatusCode != 200)
|
||||
{
|
||||
SetLastError(dwStatusCode);
|
||||
return downslib_error::statuscode;
|
||||
}
|
||||
}
|
||||
|
||||
// Get HTTP content length
|
||||
unsigned long long contentLength = 0;
|
||||
dwBufferSize = sizeof(contentLength);
|
||||
HttpQueryInfoA(hUrl, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &contentLength, &dwBufferSize, 0);
|
||||
|
||||
// Get HTTP content length
|
||||
char buffer[2048];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
DWORD dwLen = sizeof(buffer);
|
||||
unsigned long long total_bytes = 0;
|
||||
if(HttpQueryInfoA(hUrl, HTTP_QUERY_CONTENT_LENGTH, buffer, &dwLen, 0))
|
||||
{
|
||||
if(sscanf_s(buffer, "%llu", &total_bytes) != 1)
|
||||
total_bytes = 0;
|
||||
}
|
||||
|
||||
// Get HTTP status code
|
||||
dwLen = sizeof(buffer);
|
||||
if(HttpQueryInfoA(hUrl, HTTP_QUERY_STATUS_CODE, buffer, &dwLen, 0))
|
||||
{
|
||||
int status_code = 0;
|
||||
if(sscanf_s(buffer, "%d", &status_code) != 1)
|
||||
status_code = 500;
|
||||
if(status_code != 200)
|
||||
{
|
||||
SetLastError(status_code);
|
||||
return downslib_error::statuscode;
|
||||
}
|
||||
}
|
||||
|
||||
// Receive the data from the HINTERNET handle
|
||||
char buffer[chunk_size];
|
||||
DWORD dwRead = 0;
|
||||
DWORD dwWritten = 0;
|
||||
unsigned long long read_bytes = 0;
|
||||
unsigned long long readBytes = 0;
|
||||
unsigned long long totalBytes = contentLength;
|
||||
while(InternetReadFile(hUrl, buffer, sizeof(buffer), &dwRead))
|
||||
{
|
||||
read_bytes += dwRead;
|
||||
readBytes += dwRead;
|
||||
|
||||
// We are done if nothing more to read, so now we can report total size in our final cb call
|
||||
if(dwRead == 0)
|
||||
total_bytes = read_bytes;
|
||||
totalBytes = readBytes;
|
||||
|
||||
// Call the callback to report progress and cancellation
|
||||
if(cb && !cb(userdata, read_bytes, total_bytes))
|
||||
if (cb && !cb(userdata, readBytes, totalBytes))
|
||||
{
|
||||
SetLastError(ERROR_OPERATION_ABORTED);
|
||||
return downslib_error::cancel;
|
||||
|
|
@ -124,10 +137,18 @@ downslib_error downslib_download(const char* url,
|
|||
if(dwRead == 0)
|
||||
break;
|
||||
|
||||
// Write buffer to PDB file
|
||||
WriteFile(hFile, buffer, dwRead, &dwWritten, nullptr);
|
||||
|
||||
// Check WriteFile successfully wrote the entire buffer
|
||||
if (dwWritten != dwRead) {
|
||||
SetLastError(ERROR_IO_INCOMPLETE);
|
||||
return downslib_error::incomplete;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(total_bytes > 0 && read_bytes != total_bytes)
|
||||
if (totalBytes > 0 && readBytes != totalBytes)
|
||||
{
|
||||
SetLastError(ERROR_IO_INCOMPLETE);
|
||||
return downslib_error::incomplete;
|
||||
|
|
|
|||
Loading…
Reference in New Issue