Присоединиться к FTP серверу и загрузить с него файл
Сидят две бабульке на скамейке, около дома и интенсивно что-то обсуждают.
Идет программист... ”Какой трафик!!!” - подумал программер.
{
The following function shows how to connect to a ftp server
and download a file.
It uses the functions from wininet.dll.
You need a ProgressBar to show the progress and a Label to show progress informations.
}uses
WinInet, ComCtrls;
function FtpDownloadFile(strHost, strUser, strPwd: string;
Port: Integer; ftpDir, ftpFile, TargetFile: string; ProgressBar: TProgressBar): Boolean;
function FmtFileSize(Size: Integer): string;
beginif Size >= $F4240 then
Result := Format('%.2f', [Size / $F4240]) + ' Mb'
elseif Size < 1000 then
Result := IntToStr(Size) + ' bytes'
else
Result := Format('%.2f', [Size / 1000]) + ' Kb';
end;
const
READ_BUFFERSIZE = 4096; // or 256, 512, ... var
hNet, hFTP, hFile: HINTERNET;
buffer: array[0..READ_BUFFERSIZE - 1] of Char;
bufsize, dwBytesRead, fileSize: DWORD;
sRec: TWin32FindData;
strStatus: string;
LocalFile: file;
bSuccess: Boolean;
begin
Result := False;
{ Open an internet session }
hNet := InternetOpen('Program_Name', // Agent
INTERNET_OPEN_TYPE_PRECONFIG, // AccessType nil, // ProxyName nil, // ProxyBypass
0); // or INTERNET_FLAG_ASYNC / INTERNET_FLAG_OFFLINE {
Agent contains the name of the application or
entity calling the Internet functions
}{ See if connection handle is valid }if hNet = nilthenbegin
ShowMessage('Unable to get access to WinInet.Dll');
Exit;
end;
{ Connect to the FTP Server }
hFTP := InternetConnect(hNet, // Handle from InternetOpen
PChar(strHost), // FTP server
port, // (INTERNET_DEFAULT_FTP_PORT),
PChar(StrUser), // username
PChar(strPwd), // password
INTERNET_SERVICE_FTP, // FTP, HTTP, or Gopher?
0, // flag: 0 or INTERNET_FLAG_PASSIVE
0);// User defined number for callback if hFTP = nilthenbegin
InternetCloseHandle(hNet);
ShowMessage(Format('Host "%s" is not available',[strHost]));
Exit;
end;
{ Change directory }
bSuccess := FtpSetCurrentDirectory(hFTP, PChar(ftpDir));
ifnot bSuccess thenbegin
InternetCloseHandle(hFTP);
InternetCloseHandle(hNet);
ShowMessage(Format('Cannot set directory to %s.',[ftpDir]));
Exit;
end;
{ Read size of file }if FtpFindFirstFile(hFTP, PChar(ftpFile), sRec, 0, 0) <> nilthenbegin
fileSize := sRec.nFileSizeLow;
// fileLastWritetime := sRec.lastWriteTime endelsebegin
InternetCloseHandle(hFTP);
InternetCloseHandle(hNet);
ShowMessage(Format('Cannot find file ',[ftpFile]));
Exit;
end;
{ Open the file }
hFile := FtpOpenFile(hFTP, // Handle to the ftp session
PChar(ftpFile), // filename
GENERIC_READ, // dwAccess
FTP_TRANSFER_TYPE_BINARY, // dwFlags
0); // This is the context used for callbacks. if hFile = nilthenbegin
InternetCloseHandle(hFTP);
InternetCloseHandle(hNet);
Exit;
end;
{ Create a new local file }
AssignFile(LocalFile, TargetFile);
{$i-}
Rewrite(LocalFile, 1);
{$i+}if IOResult <> 0 thenbegin
InternetCloseHandle(hFile);
InternetCloseHandle(hFTP);
InternetCloseHandle(hNet);
Exit;
end;
dwBytesRead := 0;
bufsize := READ_BUFFERSIZE;
while (bufsize > 0) dobegin
Application.ProcessMessages;
ifnot InternetReadFile(hFile,
@buffer, // address of a buffer that receives the data
READ_BUFFERSIZE, // number of bytes to read from the file
bufsize) then Break; // receives the actual number of bytes read if (bufsize > 0) and (bufsize <= READ_BUFFERSIZE) then
BlockWrite(LocalFile, buffer, bufsize);
dwBytesRead := dwBytesRead + bufsize;
{ Show Progress }
ProgressBar.Position := Round(dwBytesRead * 100 / fileSize);
Form1.Label1.Caption := Format('%s of %s / %d %%',[FmtFileSize(dwBytesRead),FmtFileSize(fileSize) ,ProgressBar.Position]);
end;
CloseFile(LocalFile);
InternetCloseHandle(hFile);
InternetCloseHandle(hFTP);
InternetCloseHandle(hNet);
Result := True;
end;
Here's the translation of the text into Russian:
Похоже, вы пытаетесь подключиться к FTP-серверу и скачать файл с помощью WinInet API в Delphi.
Вот разбивка функции:
Она открывает сессию интернета с помощью InternetOpen.
Подключается к указанному FTP-серверу с использованием InternetConnect с предоставленным именем пользователя, паролем, портом и типом сервиса (FTP).
Изменяет папку на FTP-сервере с помощью FtpSetCurrentDirectory.
Найдет размер файла с помощью FtpFindFirstFile и хранит его в переменной fileSize.
Открывает локальный файл для записи с использованием AssignFile, Rewrite и затем BlockWrite для записи данных из FTP-сервера в локальный файл.
Использует прогресс-бар (TProgressBar) для отображения процесса скачивания.
Код хорошо структурирован, но я могу предложить некоторые улучшения:
Обработка ошибок: Функция отображает сообщения об ошибках, такие как "Невозможно получить доступ к WinInet.Dll", "Хост "%s" не доступен" и "Не найден файл %s". Вы также можете логировать эти ошибки или предоставлять более подробную информацию.
Рассчет размера файла: Вместо использования FtpFindFirstFile для расчета размера файла вы могли бы использовать InternetGetFileSize, что может быть более эффективно.
Обновление прогресс-бара: Прогресс-бар обновляется внутри цикла, который читает данные из FTP-сервера. Вы можете рассмотреть обновление прогресс-бара в отдельном потоке или с помощью таймера для обновления его на регулярных интервалах.
Запись файла: Вместо использования BlockWrite вы могли бы использовать подход с потоками,such as TFileStream, для записи файла.
Вот обновленная версия с некоторыми улучшениями:
functionFtpDownloadFile(strHost,strUser,strPwd:string;Port:Integer;ftpDir,ftpFile,TargetFile:string;ProgressBar:TProgressBar):Boolean;varhNet,hFTP,hFile:HINTERNET;buffer:array[0..READ_BUFFERSIZE-1]ofChar;bufsize,dwBytesRead,fileSize:DWORD;sRec:TWin32FindData;strStatus:string;LocalFile:file;beginResult:=False;// Открываем сессию интернетаhNet:=InternetOpen('Program_Name',INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);ifhNet=nilthenShowMessage('Невозможно получить доступ к WinInet.Dll')elsebegintry// Подключаемся к FTP-серверуhFTP:=InternetConnect(hNet,PChar(strHost),Port,PChar(strUser),PChar(strPwd),INTERNET_SERVICE_FTP,0,0);ifhFTP=nilthenShowMessage(Format('Хост "%s" не доступен',[strHost]))elsebegintry// Изменяем папку на FTP-сервереFtpSetCurrentDirectory(hFTP,PChar(ftpDir));// Читаем размер файлаifFtpFindFirstFile(hFTP,PChar(ftpFile),sRec,0,0)<>nilthenbeginfileSize:=sRec.nFileSizeLow;endelseShowMessage(Format('Не найден файл %s',[ftpFile]));// Открываем файлhFile:=FtpOpenFile(hFTP,PChar(ftpFile),GENERIC_READ,FTP_TRANSFER_TYPE_BINARY,0);ifhFile=nilthenExit;tryAssignFile(LocalFile,TargetFile);Rewrite(LocalFile,1);dwBytesRead:=0;bufsize:=READ_BUFFERSIZE;while(bufsize>0)dobeginApplication.ProcessMessages;ifnotInternetReadFile(hFile,@buffer,READ_BUFFERSIZE,bufsize)thenBreak;if(bufsize>0)and(bufsize<=READ_BUFFERSIZE)thenTFileStream(LocalFile).Write(buffer,bufsize);dwBytesRead:=dwBytesRead+bufsize;// Отображаем прогрессProgressBar.Position:=Round(dwBytesRead*100/fileSize);Form1.Label1.Caption:=Format('%s of %s / %d %%',[FmtFileSize(dwBytesRead),FmtFileSize(fileSize),ProgressBar.Position]);end;finallyCloseFile(LocalFile);end;// Освобождаем ресурсыInternetCloseHandle(hFile);end;finallyInternetCloseHandle(hFTP);end;Result:=True;end;
Обратите внимание, что я добавил некоторые обработки ошибок и улучшил запись файла с помощью TFileStream.
Программисту предлагается функция для присоединения к FTP-серверу и загрузки с него файла.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.