I'm super new to C++ and I'm trying to download an executable file from a URL and write it to disk.
I have the below code which successfully downloads the file and stores it in memory. The issue I am having is then writing that to disk.
I am pretty sure this is down to where I am creating the buffer where the downloaded data will be written to before being going to the new file.
char buffer[4096];
The 4096 is an arbitrary number from the template code I got elsewhere. What I can't figure out or don't know is how to dynamically allocate that buffer size based on the size of the data at &pStream.
I have tried using functions such as sizeof() but these just get me the memory address size rather than the value itself.
Alternatively, is there better way to try and accomplish this download and write?
#include <Windows.h>
#include <Urlmon.h> // URLOpenBlockingStreamW()
#include <atlbase.h> // CComPtr
#include <iostream>
#include "download.h"
#include <fstream>
#include <assert.h>
#include <chrono>
#include <thread>
#pragma comment( lib, "Urlmon.lib" )
struct ComInit
{
HRESULT hr;
ComInit() : hr(::CoInitialize(nullptr)) {}
~ComInit() { if (SUCCEEDED(hr)) ::CoUninitialize(); }
};
int download_file()
{
ComInit init;
HRESULT hr;
// use CComPtr so you don't have to manually call Release()
CComPtr<IStream> pStream;
bool success = false;
while (success == false)
{
try {
// Open the HTTP request.
hr = URLOpenBlockingStreamW(nullptr, L"https://www.foo.bar/download/somefile.exe", &pStream, 0, nullptr);
if (FAILED(hr))
{
std::cout << "ERROR: Could not connect. HRESULT: 0x" << std::hex << hr << std::dec << "\n";
}
else
{
success = true;
}
}
catch (const std::exception& ex) {
std::cout << ex.what();
}
}
// Download the response and write it to stdout.
char buffer[4096]; // Issue is here I think
do
{
DWORD bytesRead = 0;
hr = pStream->Read(buffer, sizeof(buffer), &bytesRead);
if (bytesRead > 0)
{
//std::cout.write(buffer, bytesRead);
std::ofstream file;
file.open("some_path_dot_exe", std::ios_base::binary);
assert(file.is_open());
for (int i = 0; i < sizeof(buffer) / sizeof(buffer[0]); ++i)
file.write((char*)(buffer + i * sizeof(buffer[0])), sizeof(buffer[0]));
file.close();
}
} while (SUCCEEDED(hr) && hr != S_FALSE);
if (FAILED(hr))
{
std::cout << "ERROR: Download failed. HRESULT: 0x" << std::hex << hr << std::dec << "\n";
return 2;
}
std::cout << "\n";
return 0;
}