-
Вопрос в следующем. На FTP лежит несколько файлов. Эти несколько файлов являются разрезанным архивом rar. При использовании FTPGetFile файлы скачиваются на мой компьютер. НО при попытке их собрать в архив имеем ошибку контрольной суммы. Файлы по 100 МБ. Для доступа к FTP используется прокси. В чем может быть проблема?
-
> В чем может быть проблема?
1. На ftp-сервере лежит криво порезаный архив.
2. Загружены не все файлы из оригинальной нарезки
2. Кривое использование FtpGetFile
-
1. На ftp-сервере лежит нормально нарезанный файл. (Проверено TC)
2. Файлы тоже все. Сам резал.
3. Вот это как раз и интересует. Будет ли разница если скачивать файл как ASCII или бинарный?
-
> Будет ли разница если скачивать файл как ASCII или бинарный?
Конечно будет
-
в ASCII mode "Control and formatting information is converted to local equivalents."
т.е. учитываются переводы строки, например. А они разные в *nix, mac и windows системах
-
Тогда вопрос следующий. Файл собирается, ругается на ошибку crc. После в собранный файл (rar архив) можно зайти и увидеть файл который заархивирован. Насколько я понимаю, если я принимаю файл в ASCII то у меня вообще архив бы не открывался и вообще TC его бы не воспринял как архив.
-
Кстати еще могу сказать, что при скачивании маленького файла ~10 МБ все в норме. Такая проблема наблюдается только при скачке большого файла.
-
> SortoVaritu © (19.06.09 12:05) [5]
Неправильно понимаешь.
Заголовок архива в рез-те трансфера заведомо бинарного файла как текстового оказался не испорчен (просто повезло), потому принятый файл и распознается как архив.
> могу сказать, что при скачивании маленького файла ~10 МБ
> все в норме
Опять же см. [1] п.3
-
Вот использование FtpGetFile
function FtpGetFile(
hFTP;
RemName;
LocName;
true;
0;
FTP_TRANSFER_TYPE_BINARY;
0);
-
Вот хэндлы
hNet := InternetOpen('Program_Name',
INTERNET_OPEN_TYPE_PRECONFIG,
nil,
nil,
0);
hFTP := InternetConnect(hNet,
MyServer,
21,
Username,
Password,
INTERNET_SERVICE_FTP,
0,
0);
-
А где анализ результата вызова ?
-
анализ есть. Это я просто из тела программы вырвал саму FtpGetFile и хэндлы. Грубо говоря если сделано так, что если на FTP в определенный католог не законнектится, то FtpGetFile просто не вызывается.
-
А если вызывается, то где анализ возвращенного ею рез-та ?
-
Вот тут и вопрос.
function FtpGetFile(
hFTP;
RemName;
LocName;
true;
0;
FTP_TRANSFER_TYPE_BINARY;
0)=FALSE. Всегда. То есть файл скачивается, но FtpGetFile возвращает False все равно.
-
Return Value
Returns TRUE if successful, or FALSE otherwise. To get a specific error message, call GetLastError.
-
Хорошо попробую использовать GetLastError. Но если чисто теоретически, то в чем может быть загвоздка? (ПОнимаю что нужно смотреть GetLastError). Просто на форумах куча примеров и у всех вроде как работает FtpGetFile нормально. И размер файла на сервере и скачанного тоже вроде как идентичны.
-
Загвозку есть резон искать лишь после анализа кода отказа.
-
Возможно ли, что хэндлы закрываются быстрее чем выполняется FtpGetFile?
-
Ну чего ты гадаешь-то ?)
Давно уж написал бы
Win32Check(FtpGetFile(..));
тогда бы и разговор был предметный о причинах ..
-
Заранее извиняюсь. Сейчас не имею доступа к FTP.
-
Ну вот как поимеешь, так сразу и милости просим)
-
Так. Ошибка 12111. Что как я понял означает прерывание сессии с FTP.
-
Точно так - FTP-сессия была прервана.
Ни о каких контр.суммах при этом, естественно, не может идти и речи.
-
Хорошо. А как с этим бороться?
-
выесняй почему сессия рвется
-
Хм. Трудный вопрос. При скачивании тотал коммандером все ОК. Коммандер использует для этого комманды для FTP. А сессия рвется всегда в самом конце закачки. То есть я так понимаю, что файл скачивается, в последний момент моя софтина отсылает какой-то запрос на сервер и тут выясняется, что сессия уже разорвана.
-
> А сессия рвется всегда в самом конце закачки
не факт
-
Для начала убедись, что сессию рвет не файрвол и не прокси.
-
> сессию рвет не файрвол и не прокси
они не могут этого сделать, тк соединение установлено
-
Вот в том то и дело. Вообщем-то нигде данная ситуация и не описана. Да и в случае с коммандером ведь прокси сессию не рвет, а файервол у меня отрублен.
-
снифь порт и смотри, в чем различия (твоя прога и командер тотал)))))
-
Есть еще вопрос. Если вместо FTPGetFile использовать FTPCommand. Вернее я это уже пробую. Но есть загвоздка.
При выполнении FtpCommand(hFtp,true,FTP_TRANSFER_TYPE_BINARY,
PChar('RETR '+MyFile),0,hFile) у меня выходит ошибка переполнения памяти. А вот комманда FtpCommand(hFtp,true,FTP_TRANSFER_TYPE_ASCII,
PChar('LIST'),0,hFile) выполняется без проблем.
-
> они не могут этого сделать
Еще как могут
-
> Еще как могут
на каком основании позволь полюбопытствовать?
-
Кстати данная проблема не только с моей прогой, но и с некоторыми FTP клиентами.
-
-
Так я по этой ссылке и читал использование FTPCommand. Там получается, что при успешном выполнении данной комманды должна сгенерироваться переменная hFIle. Так она я так понял и генерируется, только почему то ошибку с памятью выбрасывает.
-
Что, вот прямо так и говорит "я, ошибка переполнения памяти, выхожу" или "меня, ошибку, выбросили вместе с памятью" ?
Ты не в состоянии привести дословный текст увиденного тобой, да ?
-
access violetion at address "адрес не помню". write to address FFFFFFFFF
-
> только почему то ошибку с памятью выбрасывает.
> access violetion at address
мдя(
-
И что сие может озночать
-
много чего...
-
И как быть
-
> как быть
Адрес запоминать)
И внимательно изучать прототип ф-ции.
-
а что не так с прототипом функции?
-
А я откуда знаю, что у тебя там с ним не так ?
Мне отсюда не видать)
-
ну стандартно: ошибка в 17 строке
-
FtpCommand(hFtp,true,FTP_TRANSFER_TYPE_BINARY,
PChar('RETR '+MyFile),0,hFile)
Функция вызывается вызывается следующим образом
function FtpCommand(
hConnect: HINTERNET;
fExpectResponse: BOOL;
dwFlags: DWORD;
lpszCommand: PChar;
dwContext: DWORD;
var phFtpCommand: PHINTERNET): BOOL;
stdcall; external 'wininet.dll' name 'FtpCommandA';
Вроде бы как все сделано верно.
-
> FtpCommand(hFtp,true,FTP_TRANSFER_TYPE_BINARY,
> PChar('RETR '+MyFile),0,hFile)
> Функция вызывается вызывается следующим образом
>
> function FtpCommand(
> hConnect: HINTERNET;
> fExpectResponse: BOOL;
> dwFlags: DWORD;
> lpszCommand: PChar;
> dwContext: DWORD;
> var phFtpCommand: PHINTERNET): BOOL;
> stdcall; external 'wininet.dll' name 'FtpCommandA';
О_о ?
-
Поясните еще hFTP:HINTERNET а hFile:PHINTERNET. В чем разница?
-
вообще, я думал это хэндлы, но
> hFTP:HINTERNET а hFile:PHINTERNET. В чем разница?
хэндл и поинтер?
-
> SortoVaritu © (22.06.09 12:14) [47]
Судя по этому прототипу у тебя и 'LIST' не должна работать)
-
FtpCommand(hFtp,true,FTP_TRANSFER_TYPE_BINARY,
PChar('RETR '+MyFile),0,hFile). Хорошо hFile Это поинтер. А как тогда создать хэндл?
-
А как объявлен PHINTERNET ?
-
PHINTERNET=^HINTERNET
-
может быть
phFile:=@hFile;
FtpCommand(hFtp,true,FTP_TRANSFER_TYPE_BINARY,
PChar('RETR '+MyFile),0,phFile)
-
Ясно.
Выкинь в топку свой прототип - его формировал кто-то без головы на плечах.
function FtpCommand(
hConnect: HINTERNET;
fExpectResponse: BOOL;
dwFlags: DWORD;
lpszCommand: PChar;
dwContext: DWORD;
var hFtpCommand: HINTERNET): BOOL;
stdcall; external 'wininet.dll' name 'FtpCommandA';
-
-
FtpCommand(m_hFtpSession,true,FTP_TRANSFER_TYPE_ASCII,
PChar('NLST'),0,@data_handle) Это в примерет так написано.
@data_handle - Это ведь и есть поинтер для Хэндла или я ошибаюсь.
-
> непонятно, что должна возвращать функция Хэндл или поинтер
Читаешь первоисточник - MSDN - и все становится понятным:
__out HINTERNET *phFtpCommand
..
phFtpCommand [out]
A pointer to a handle that is created if a valid data socket is opened. The fExpectResponse parameter must be set to TRUE for phFtpCommand to be filled.
Т.е. если
var
hFile: HINTERNET;
то при
var hFtpCommand: HINTERNET
вызов такой:
FtpCommand(.., hFile)
а при
pFtpCommand: PHINTERNET
вызов уже иной:
FtpCommand(.., @hFile)
-
Будет ли правильным:
function FtpCommand(
hConnect: HINTERNET;
fExpectResponse: BOOL;
dwFlags: DWORD;
lpszCommand: PChar;
dwContext: DWORD;
var phFtpCommand: PHINTERNET): BOOL;
stdcall; external 'wininet.dll' name 'FtpCommandA';
procedure TForm1.Button1Click(Sender: TObject);
var
phFile :PHINTERNET;
hFile,hftp:HINTERNET;
begin
.......
phfile:=@hfile;
FtpCommand(hFtp,true,FTP_TRANSFER_TYPE_ASCII,
PChar('LIST'),0,phfile);
.......
end;
-
> что должна возвращать функция Хэндл или поинтер
Она должна вернуть хэндл, записав его по адресу, переданному последним параметром.
-
То есть если записать так
phfile:=@hfile;
FtpCommand(hFtp,true,FTP_TRANSFER_TYPE_ASCII,
PChar('LIST'),0,phfile);
будет верным, т.к
FtpCommand(.., @hFile) компилятор ругается на несовпадение типов
-
Что то я понять не могу.
FtpCommand(hFtp,true,FTP_TRANSFER_TYPE_ASCII,
PChar('LIST'),0,phfile); где phfile:PHinternet. Почему тогда ошибка выпрыгивает. Ведь phfile это адрес где записан хэндл. В чем тогда проблема состоит.
-
> SortoVaritu © (22.06.09 13:42) [63]
что тебе не понятно в [59] ?
-
да можно и так
function FtpCommand(
hConnect: HINTERNET;
fExpectResponse: BOOL;
dwFlags: DWORD;
lpszCommand: PChar;
dwContext: DWORD;
phFtpCommand: PHINTERNET): BOOL;
stdcall; external 'wininet.dll' name 'FtpCommandA';
-
Я так понимаю в последнем параметре нужно указать адрес моего хэндла hFTP, дабы функция по этому адресу вывела мне сам хэндл.
-
Правильно понимаешь
-
ОК. Баааааааааааааааааааааальшое спасибо за помощь. Премного благодарен. Вечером попробую.
-
Итак. Что получилось.
При таком коде все работает правильно.
s:=PChar('LIST') ;
FtpCommand1(hftp,true,FTP_TRANSFER_TYPE_BINARY ,s ,0,phFile);
err:=12003;
InternetGetLastResponseInfo(err, @Msg, Len);
form1.memo1.lines.add(StrPas(@msg));
begin
AssignFile(LocalFile, ExtractFilepath(Application.exeName)+sRec .cFileName);
{$i-}
Rewrite(LocalFile, 1);
{$i+}
dwBytesRead := 0;
bufsize := READ_BUFFERSIZE;
while (bufsize > 0) do
begin
Application.ProcessMessages;
if not InternetReadFile(phFile,
@buffer,
READ_BUFFERSIZE,
bufsize) then Break;
read
if (bufsize > 0) and (bufsize <= READ_BUFFERSIZE) then
BlockWrite(LocalFile, buffer, bufsize);
dwBytesRead := dwBytesRead + bufsize;
CloseFile(LocalFile);
end;
Но если команда не LIST а RETR. То выпрыгивает выше упомянутая ошибка с памятью.
-
> FtpCommand1(hftp,true,FTP_TRANSFER_TYPE_BINARY ,s ,0,phFile);
И вновь нет анализа результата вызова API-функции, см.[12] !
Упрямство, достойное ослиного)
> err:=12003;
> InternetGetLastResponseInfo(err, @Msg, Len);
Это что за пляски с бубном ?
Что еще за "err:=12003" ? С какой луны свалилось число 12003 ?
Код ответа сервера следует получать (а не самому устанавливать от балды взятое значение !) лишь после успешного выполнения API-ф-ции, обращающейся к серверу.
И опять же - где анализ результата вызова InternetGetLastResponseInfo ?
И если вызов InternetGetLastResponseInfo успешен, где анализ значения, возвращенного этой ф-цией в переменную err ?
Когда ты наконец начнешь читать документацию, прежде чем что-то писать ?)
-
12003 значение взятое не от балды.
Да и причем тут это.
Для того чтобы получить результат вызова InternetGetLastResponseInfo нужно чтобы FtpCommand1(hftp,true,FTP_TRANSFER_TYPE_BINARY ,s ,0,phFile) выполнился. А он выполняется только с командой LIST. А с коммандой RETR нет. Что анализировать если команда не выполняется?
-
>И если вызов InternetGetLastResponseInfo успешен, где анализ значения, возвращенного этой ф-цией в переменную err ?
Как он может быть успешен если прога даж не доходит до выполнения InternetGetLastResponseInfo
-
> А он выполняется
А где в твоем коде видно что выполняется или не выполняется ?
Почему я должен верить тебе на слово ?)
> 12003 значение взятое не от балды
А откуда ?)
> Да и причем тут это
А нашиша тогда ты демонстрируешь этот бестолковый код, не имеющий к проблеме отношения ?
И, наоборот, упрямо не приводишь код, имеющий непосредственное отношение к выяснению проблемы (анализ результатов вызовов API-функций и соотв.ветвления последующего алгоритма) ?
> выше упомянутая ошибка с памятью
Опять адрес забыл ?)
-
> Как он может быть успешен если прога даж не доходит до выполнения
> InternetGetLastResponseInfo
>
Вот как будет доходить, так и будем рассматривать работу InternetGetLastResponseInfo.
А пока это абсолютно бессмысленный код.
-
Так он не бессмысленный. Он работает если команду выполнять LIST. Он мне в файл записывает содержимого каталога. РАБОТАЕТ.
НЕ РАБОТАЕТ при выполнении команды RETR.
В чем же он тогда бессмысленный.
-
Так он не бессмысленный. Он работает если команду выполнять LIST. Он мне в файл записывает содержимого каталога. РАБОТАЕТ.
НЕ РАБОТАЕТ при выполнении команды RETR.
В чем же он тогда бессмысленный.
-
> он не бессмысленный. Он работает если команду выполнять
> LIST
Он бессмысленный при любой команде !
Ф-ция InternetGetLastResponseInfo не получает, а возвращает код ответа сервера !
За ккаким же лешим ты пишешь какое-то число в переменную err, если следом же вызываешь InternetGetLastResponseInfo, задача которой - изменить значение этой переменной в случае успешного выполнения ф-ции ?
-
Изучай:
function FtpCommand(
hConnect: HINTERNET;
fExpectResponse: BOOL;
dwFlags: DWORD;
lpszCommand: PChar;
dwContext: DWORD;
var hFtpCommand: HINTERNET): BOOL;
stdcall; external 'wininet.dll' name 'FtpCommandA';
const
url = 'ftp://ftp.freepascal.org/fpc/contrib/cross/linux/';
procedure TForm1.Button5Click(Sender: TObject);
var
hInet, hFTPSession, hFile: HINTERNET;
RCode, RTLen: Cardinal;
RText: String;
begin
hInet := InternetOpen('FTP', INTERNET_OPEN_TYPE_PROXY, '192.168.7.254:3128', nil, 0);
Win32Check(Assigned(hInet));
try
hFTPSession := InternetConnect(hInet, 'ftp.freepascal.org', 21, nil, nil, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
Win32Check(Assigned(hFTPSession));
try
Win32Check(FtpCommand(hFTPSession, True, FTP_TRANSFER_TYPE_BINARY, 'RETR /fpc/contrib/cross/linux/binutils-fpc-netware.spec', 0, hFile));
try
RTLen := 255;
SetLength(RText, RTLen);
RCode := 12003;
Win32Check(InternetGetLastResponseInfo(RCode, PChar(RText), RTLen));
SetLength(RText, RTLen);
ShowMessage('Response code = ' + IntToStr(RCode) + #10#10'Response text is'#10#10 + RText)
finally
InternetCloseHandle(hFile);
end;
finally
InternetCloseHandle(hFTPSession);
end;
finally
InternetCloseHandle(hInet);
end;
end;
-
За совет, спасибо. Это все я понимаю. То что лишний код оставил, так это у меня всегда такой мусор валяецца. Признаю. Только ведь InternetGetLastResponseInfo не выполняется даже. Софтина останавливается на ошибке памяти.
-
Вот кстати еще хотел спросить. Чем отличается запрос файла командой FTPGetFile и командой RETR.
-
> у меня всегда такой мусор валяецца
И кому, как думаешь, интересно или приятно взирать на твой "мусор" ?
Ты пойми - если ты процитировал некий код, то подразумевается, что ты уверен в том что он имеет прямое отношение к твоей задаче или проблеме в ее решении, т.е. он имеет некое осмысленное немаловажное значение, коль скоро он фигурирует ..
> Чем отличается запрос файла командой FTPGetFile и командой
> RETR
FTPGetFile неявно подает команду RETR, получает содержимое удаленного файла и записывает полученное содержимое в указанный тобой файл.
-
Проще говоря FTPGetFile так же использует команду RETR для доступа к файлу.
-
Конечно.
А как же иначе ?
-
Хм. Тогда я вот думаю. Решится ли мой вопрос с разрывом сессии, если я буду использовать напрямую RETR вместо FTPGETFile.
-
Ты уже код [78] изучил ? Опробовал на своих "больших" файлах ? Каковы результаты ?
Излагай подробно и дословно все что видишь при его выполнении ..
-
Результат точно такой же.
Access violation at adress 77C32A16 in module msvcrt.dll. Read of adress FFFFFFFF
-
Что за ОС ? Какая версия Делфи ?
-
Windows XP SP3. Delphi 7.
Я вот тоже думаю, что не в проге дело.
-
Ты это код пробовал "один в один" ?
Или свои изменения внес ?
Если внес, показывай весь этот фрагмент со своими изменениями ..
-
код внес один в один. только сервер свой подставил ну и имя файла тож который на сервере лежит а так один в один
-
> код внес один в один. только сервер свой подставил
И это ты называешь "один в один" ?)
Приводи текст с изменениями ..
-
function FtpCommand(
hConnect: HINTERNET;
fExpectResponse: BOOL;
dwFlags: DWORD;
lpszCommand: PChar;
dwContext: DWORD;
var hFtpCommand: HINTERNET): BOOL;
stdcall; external 'wininet.dll' name 'FtpCommandA';
const
url = 'vh22.win.hoster.by';
procedure TForm1.Button5Click(Sender: TObject);
var
hInet, hFTPSession, hFile: HINTERNET;
RCode, RTLen: Cardinal;
RText: String;
begin
hInet := InternetOpen('FTP', INTERNET_OPEN_TYPE_DIRECT, nil, nil, 0);
Win32Check(Assigned(hInet));
try
hFTPSession := InternetConnect(hInet, 'vh22.win.hoster.by', 21, login, password, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
Win32Check(Assigned(hFTPSession));
try
Win32Check(FtpCommand(hFTPSession, True, FTP_TRANSFER_TYPE_BINARY, 'RETR 1.txt', 0, hFile));
try
RTLen := 255;
SetLength(RText, RTLen);
RCode := 12003;
Win32Check(InternetGetLastResponseInfo(RCode, PChar(RText), RTLen));
SetLength(RText, RTLen);
ShowMessage('Response code = ' + IntToStr(RCode) + #10#10'Response text is'#10#10 + RText)
finally
InternetCloseHandle(hFile);
end;
finally
InternetCloseHandle(hFTPSession);
end;
finally
InternetCloseHandle(hInet);
end;
end;
-
> Для доступа к FTP используется прокси
Ну и где у тебя в коде используется прокси ?
Нпапрямую же лезешь к ресурсу ..
-
Блин. Я уже и прокси не использую. На прямую делаю. Чтобы исключить любую вероятность его вмешательства.
-
И какой же размер у 1.txt ?
-
> На прямую делаю
Доступ в Тырнет у тебя прямой или из корп.сети ?
-
У меня есть и такой и такой. Все это я делаю дома. Дома у меня доступ прямой. Прямое соединение через провайдера.
-
Хочешь сказать, что способ доступа не влияет ?
Т.е. один и тот же код (без использования прокси) не работает ни здесь ни там, возбуждая одно и тио же исключение на одной и той же строчке ?
Ну хорошо.
А мой код (один в один или без использования прокси) ТОЖЕ возбуждает исключение при разных условиях способах доступа ?
-
Так точно. FTPCommand выбрасывает одну и ту же ошибку
-
А как узнал, что имеенно FTPCommand, а не что-то иное ?
В отладике пошагово или как ?
-
Да. Пошагово отлаживал.
-
А декларация FTPCommand у тебя случаем не кривая ?
Покажи-ка ее ..
-
function FtpCommand(
hConnect: HINTERNET;
fExpectResponse: BOOL;
dwFlags: DWORD;
lpszCommand: PChar;
dwContext: DWORD;
var hFtpCommand: HINTERNET): BOOL;
stdcall; external 'wininet.dll' name 'FtpCommandA';
Если ты это имеешь ввиду, то я же у тебя ее и скопировал. Только вот последний параметр меня смущает.
-
> последний параметр меня смущает
Он тебя не должен смущать, ибо у меня код успешно работает.
А что собссно смущает-то ? Уже жевали-пережевали этот вопрос в начале топика ..
-
Хотя в общем ты прав. Думаешь проблема с компилятором или с с системой? Возможно с Wininet.dll?
-
Ты экспериментируешь в заведомо "чистом" тестовом проекте или в "боевом" ?
-
В чистом проекте. Твой код я вставил в абсолютно чистый проект.