C++ 自定義url下載數據類

url下載文件類

主要是常見代碼做個整理

AutoString iutiltools 都是自定義的類型.和本類無關.

code

.h

#pragma once
#include "IUtileTools.h"
#include <UrlMon.h>//download file   URLDownloadToFile
#pragma comment(lib, "urlmon.lib")
#pragma comment(lib,"Wininet.lib")
//URLDownloadToFile(NULL, url, filename, 0, NULL);//download with the second way

class CUrls : public IUtileTools
{

public :
	CUrls();
	~CUrls();
public:

	

	
	bool downloadToMemory(AutoString Url, OUT char*& ptrData, OUT int& ptrdata_size);
	/*
	參數1: 下載的url
	參數2: 下載到的文件路徑 給全路徑 如: c:\xxx\temp\abc 那麼下載的數據就是此文件
	*/
	bool downloadToFile(wstring url, wstring fileName);
	
	//解密數據並且寫入到指定文件中
	bool WriteFileToSpecialFilePath(
		AutoString FileName, 
		void* writeBuffer, 
		int buffersize,
		bool isEntry);
private:
	//下載到文件
	/*
	參數1: 要下載的url鏈接
	參數2: 下載到哪裏,給一個全路徑的文件名。
	*/
	bool download(AutoString Url, AutoString filename);
	bool downloadToFileByWinapi(wstring url, wstring fileName);
	//下載到內存
	/*
	參數1,要下載數據的url
	參數2,下載的數據內存,數據下載好之後會存放到內存中.
	*/
	bool downloadToBuffer(AutoString Url, OUT char*& ptrData, OUT int& ptrdata_size);
	bool downloadToFileStream(wstring Url, OUT char*& ptrData, OUT int& ptrdata_size);
};

.cpp

#include "CUrls.h"
#include <Windows.h>
#include <wininet.h>
#include <iostream>
#include "base64.h"
#include <fstream>
#include <Urlmon.h>
//#pragma comment(lib,"Winhttp.lib")
#pragma comment(lib, "Urlmon.lib")


using namespace std;
CUrls::CUrls()
{
}
CUrls::~CUrls()
{
}

bool CUrls::downloadToBuffer(AutoString Url,OUT char *&ptrData,OUT int &ptrdata_size)
{
	byte Temp[4096];
	memset(Temp, 0, 4096);
	ULONG Number = 1;


	int BufferSize = 0;
	char* recvdata = nullptr;
	memset(recvdata, 0, BufferSize); 
	//INTERNET_FLAG_ASYNC
	//INTERNET_FLAG_FROM_CACHE
	
	HINTERNET hSession = InternetOpen(TEXT("RookIE/1.0"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
	HINTERNET handle2 = nullptr;
	if (hSession != NULL)
	{
		handle2 = InternetOpenUrl(hSession, Url.c_str(), NULL, 0, INTERNET_FLAG_DONT_CACHE, 0);
		if (handle2 != NULL)
		{
			vector<char*> Memary;
			while (Number > 0)
			{
				char* TempBuffer = new char[4096]();
				InternetReadFile(handle2, TempBuffer, 4096, &Number);  
				Memary.push_back(TempBuffer);
			} 
			//合併內存
			DWORD  MmearySize = Memary.size();
			DWORD  AllocSize = MmearySize * 4096; 
			recvdata = (char*)VirtualAlloc(0, AllocSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
			if (recvdata != nullptr)
			{
				char* pstart = recvdata;
				for (DWORD i = 0; i < Memary.size(); i++)
				{
					if (recvdata != 0)
					{
						memcpy(recvdata, Memary[i], 4096);
					}

					recvdata += 4096;
				}

				//釋放內存
				for (DWORD i = 0; i < Memary.size(); i++)
				{
					delete[] Memary[i];
				}
				ptrData = pstart;
				ptrdata_size = AllocSize;
			}
		}
		else
		{
			goto ERROR_OPT;
		}
	}
	else
	{
		goto ERROR_OPT;
	}

	if (handle2 != NULL)
	{
		InternetCloseHandle(handle2);
		handle2 = NULL;
	}
	else
	{
		handle2 = NULL;
	}

	if (hSession != NULL)
	{

		InternetCloseHandle(hSession);
		hSession = NULL;
	}
	else
	{
		hSession = NULL;
	}

	return true;

ERROR_OPT:

	if (handle2 != NULL)
	{
		InternetCloseHandle(handle2);
		handle2 = NULL;
	}
	else
	{
		handle2 = NULL;
	}

	if (hSession != NULL)
	{

		InternetCloseHandle(hSession);
		hSession = NULL;
	}
	else
	{
		hSession = NULL;
	}
	return false;
}
bool CUrls::download(AutoString Url, AutoString filename)
{


	/*
	每次下載之前判斷是否下載過了.或者說刪除cfg文件來達到命令只執行一次
	*/
	byte Temp[1024];
	ULONG Number = 1;

	FILE* stream;

	HINTERNET hSession = InternetOpen(TEXT("RookIE/1.0"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
	HINTERNET handle2 = nullptr;
	if (hSession != NULL)
	{
		handle2 = InternetOpenUrl(hSession, Url.c_str(), NULL, 0, INTERNET_FLAG_DONT_CACHE, 0);
		if (handle2 != NULL)
		{

#ifdef _UNICODE
			if ((stream = _wfopen(filename.c_str(), TEXT("wb"))) != NULL)
#else
			if ((stream = fopen(filename.c_str(), "wb")) != NULL)
#endif
			{
				while (Number > 0)
				{
					InternetReadFile(handle2, Temp, 1024, &Number);  //每次讀取1024個字節並且寫入到文件

					fwrite(Temp, sizeof(char), Number, stream);
				}
				fclose(stream);
			}
		}
		else
		{
			goto ERROR_OPT;
		}
	}
	else
	{

		goto ERROR_OPT;
	}


	if (handle2 != NULL)
	{
		InternetCloseHandle(handle2);
		handle2 = NULL;
	}
	else
	{
		handle2 = NULL;
	}

	if (hSession != NULL)
	{

		InternetCloseHandle(hSession);
		hSession = NULL;
	}
	else
	{
		hSession = NULL;
	}
	return true;
ERROR_OPT:

	if (handle2 != NULL)
	{
		InternetCloseHandle(handle2);
		handle2 = NULL;
	}
	else
	{
		handle2 = NULL;
	}

	if (hSession != NULL)
	{

		InternetCloseHandle(hSession);
		hSession = NULL;
	}
	else
	{
		hSession = NULL;
	}
	return false;

	
}

bool CUrls::downloadToFileByWinapi(wstring url, wstring fileName)
{
	HRESULT ret = URLDownloadToFileW(
		nullptr,
		url.c_str(),
		fileName.c_str(),
		0,
		nullptr
	);

	if (ret != S_OK)
		return false;
	return true;
}

bool CUrls::downloadToMemory(AutoString Url, OUT char*& ptrData, OUT int& ptrdata_size)
{
	bool bRet = false;
	char* pdata = nullptr;
	int pdatasize = 0;
	bRet = downloadToFileStream(Url, ptrData, ptrdata_size);
	if (bRet)
	{
		
		return true;
	}
	bRet = downloadToBuffer(Url, ptrData, ptrdata_size);
	if (bRet)
	{
		
		return true;
	}

	return false;
}

bool CUrls::downloadToFile(wstring url,wstring fileName)
{
	bool bRet = false;
	bRet = downloadToFileByWinapi(url,fileName);
	if (bRet != false)
	{
		return true;
	}
	bRet = this->download(url, fileName);
	if (bRet != false)
	{
		return true;
	}
	return false;

}

bool CUrls::downloadToFileStream(wstring Url, OUT char*& ptrData, OUT int& ptrdata_size)
{
	IStream* stream; // 存後面的流

	HRESULT ret = URLOpenBlockingStreamW(
		nullptr,
		Url.c_str(),
		&stream,
		0,
		nullptr
	);

	if (ret != S_OK)
		return false;

	char buffer[4096] = { 0 };
	vector<char*> ptr_vec;
	DWORD readBytes = 0;
	do
	{
		stream->Read(   // 讀取流中的數據
			buffer,     // 緩衝區
			4096,       // 緩衝區大小
			&readBytes  // 用來存儲讀取到的字節數。
		);
		char* ReadBuffer = new char[4096]();
		RtlCopyMemory(ReadBuffer, buffer, 4096);
		ptr_vec.push_back(ReadBuffer);
	} while (readBytes > 0); // 直到讀取完畢(讀取字節數爲 0)
	DWORD Memorysize = ptr_vec.size();
	DWORD allocSize = Memorysize * 4096;
	char* ptrReadData = (char *)VirtualAlloc(0, allocSize, MEM_COMMIT, PAGE_READWRITE);
	char* pStart = nullptr;
	if (ptrReadData != nullptr)
	{
		pStart = ptrReadData; // 記錄起始位置
	}
	for (DWORD i = 0; i < Memorysize; i++)
	{
		RtlCopyMemory(ptrReadData, ptr_vec[i], 4096);
		ptrReadData += 4096;
	}
	//釋放掉ptr_vec的內存.拷貝過的內存不需要了.
	for (DWORD i = 0; i < Memorysize; i++)
	{
		if (ptr_vec[i] != nullptr)
		{
			delete[] ptr_vec[i];
			ptr_vec[i] = 0;
		}
	}
	stream->Release(); // 釋放掉

	ptrData = pStart;
	ptrdata_size = allocSize;
	return true;
}

bool CUrls::WriteFileToSpecialFilePath(
	AutoString FileName,
	void* writeBuffer,
	int buffersize,
	bool isEntry)
{
	if (isEntry)
	{
		//解密數據寫入到本地
		int outlen = 0;
		unsigned char *decryptBuffer = base64_decode((const char *)writeBuffer, buffersize, &outlen);

		FILE* pFile = NULL;
#ifdef _UNICODE
		_wfopen_s(&pFile, FileName.c_str(), L"wb");
#else
		fopen_s(&pFile, FileName.c_str(), "wb");
#endif
		if (pFile != NULL)
		{
			fwrite(decryptBuffer, outlen, 1, pFile);
			if (pFile != NULL)
			{
				fclose(pFile);
				pFile = NULL;
				if (decryptBuffer != NULL)
				{
					free(decryptBuffer);
					decryptBuffer = NULL;

				}
				return true;
			}
			if (decryptBuffer != NULL)
			{
				free(decryptBuffer);
				decryptBuffer = NULL;

			}
			return false;
		}
	}
	return false;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章