PDA

Просмотр полной версии : [Помогите!] Загрузка больших файлов на C++


Annedroid
04.04.2013, 22:47
Всем привет,
Моя программа загружает нужный компонент с сайта, раньше он весил 17 кб / 17 408 байт и можно было просто поставить максимальный размер буффера в функции (65 536) и эта проблема как бы отходила, но после упаковки файл стал весить 1,35 МБ, стало быть это 1 421 312 байт, мне нужен правильный код, чтобы выделить память, скачать, сохранить в файл и освободить память.
Вот мой предыдущий код:

int Get( char* szUrl, char* szFile )
{
BYTE cBuffer[ INTERNET_GET_MAX ];

HINTERNET hInternet = InternetOpenA( INTERNET_LOGIN, INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0 );

HINTERNET hFile = InternetOpenUrlA( hInternet, szUrl, 0, 0, INTERNET_FLAG_RELOAD, 0 );

DWORD dwReadSize = INTERNET_GET_MAX - 1;

int uResult = InternetReadFile( hFile, cBuffer, dwReadSize, &dwReadSize );

cBuffer[ dwReadSize ] = '\0';

InternetCloseHandle( hInternet );
InternetCloseHandle( hFile );

if ( uResult )
{
DeleteFileA( szFile );

HANDLE hOutputFile = CreateFileA( szFile, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0 );

uResult = WriteFile( hOutputFile, cBuffer, dwReadSize, &dwReadSize, 0 );

CloseHandle( hOutputFile );

return ( uResult ) ? ( uResult ) : ( 0 - GetLastError( ) );
}

return ( 0 - GetLastError( ) );
}

INTERNET_GET_MAX - 65 536, как уже писала ранее.
Возможно удастся как-то по частям загрузить.
П.с. курила malloc, все равно не очень понятно.
Заранее спасибо вам.

twice
05.04.2013, 01:17
int Get( char* szUrl, char* szFile )
{
BYTE *cBuffer = NULL;
DWORD dwReadSize = 0;

HINTERNET hInternet = InternetOpenA( INTERNET_LOGIN, INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0 );

HINTERNET hFile = InternetOpenUrlA( hInternet, szUrl, 0, 0, INTERNET_FLAG_RELOAD, 0 );

if (!InternetQueryDataAvailable(hFile, &dwReadSize, 0, 0))
return -1;

cBuffer = new BYTE[dwReadSize];
if (!cBuffer)
return -2;

int uResult = InternetReadFile( hFile, cBuffer, dwReadSize, &dwReadSize );

cBuffer[ dwReadSize ] = '\0';

InternetCloseHandle( hInternet );
InternetCloseHandle( hFile );

if ( uResult )
{
DeleteFileA( szFile );

HANDLE hOutputFile = CreateFileA( szFile, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0 );

uResult = WriteFile( hOutputFile, cBuffer, dwReadSize, &dwReadSize, 0 );

CloseHandle( hOutputFile );

return ( uResult ) ? ( uResult ) : ( 0 - GetLastError( ) );
}

delete [] cBuffer;

return ( 0 - GetLastError( ) );
}

Как то так.
- Запрос размера файла через InternetQueryDataAvailable
- Динамически выделяем память в соответствии с размером доступного файла

И, если выходишь из функции прямо из "if", то не забудь сначала освободить память (delete [] cBuffer).

За основу взята инфа из RSDN - [Ссылки могут видеть только зарегистрированные и активированные пользователи]

Annedroid
05.04.2013, 15:49
Как то так.
- Запрос размера файла через InternetQueryDataAvailable
- Динамически выделяем память в соответствии с размером доступного файла

И, если выходишь из функции прямо из "if", то не забудь сначала освободить память (delete [] cBuffer).

За основу взята инфа из RSDN - [Ссылки могут видеть только зарегистрированные и активированные пользователи]

Спасибо вам, ваш код работает!
П.с. если кому-то нужен мой класс AInternet:
rghost ( заголовочный файл ) ([Ссылки могут видеть только зарегистрированные и активированные пользователи])

twice
05.04.2013, 16:40
И, если выходите из функции прямо из "if", то не забудьте сначала освободить память (delete [] cBuffer).


if ( uResult )
{
DeleteFileA( szFile );

HANDLE hOutputFile = CreateFileA( szFile, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_ALWAYS, 0, 0 );

uResult = WriteFile( hOutputFile, cBuffer, dwReadSize, &dwReadSize, 0 );

CloseHandle( hOutputFile );

return ( uResult ) ? ( uResult ) : ( 0 - GetLastError( ) );
}


Перед return забыто "delete [] cBuffer", что приведет к утечки памяти при правильном исходе работы функции (функция Get). ;)

Также рекомендую обернуть все содержимое заголовочника в

#ifndef AINTERNET_H
#define AINTERNET_H
тут тело заголовочника
#endif


Это поможет избежать ошибок компиляции/линковки, если данный заголовочник будет подключен в нескольких модулях.

Annedroid
05.04.2013, 17:58
Спасибо... Учила, а не все помню...

twice
11.05.2013, 15:03
Annedroid, взяв твой класс за основу, немного доработал его.

[Ссылки могут видеть только зарегистрированные и активированные пользователи]

Может кому-нибудь пригодится.