Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Решение проблемы потоковой загрузки с IdFTP в Android с помощью Delphi

Delphi , Интернет и Сети , FTP

Решение проблемы потоковой загрузки с IdFTP в Android с помощью Delphi

При работе с потоковой загрузкой файлов с помощью IdFTP в Android на платформе Delphi могут возникнуть проблемы, когда загрузка застревает на этапе "Разрешение имени хоста". В этой статье мы рассмотрим решение этой проблемы и приведем примеры кода на Object Pascal (Delphi).

Описание проблемы

При использовании IdFTP для загрузки файлов без потока все работает корректно. Однако, при попытке сделать загрузку потоковой, процесс застревает на этапе "Разрешение имени хоста" в операционной системе Android.

Пример кода без потока (работает корректно):

uses ..., IdFTPCommon;

var
  RecordDownload: TMemoryStream;

uses System.IOUtils;

procedure TForm1.Button1Click(Sender: TObject);
begin
  IdFTP1.Host := 'motoristaajudante.ddns.net';
  IdFTP1.Port := 2121;
  IdFTP1.DataPortMin := 50100;
  IdFTP1.DataPortMax := 51100;
  IdFTP1.Username := 'anonymous';
  IdFTP1.TransferType := IdFTPCommon.TIdFTPTransferType.ftBinary;
  IdFTP1.Passive := True;
  try
    IdFTP1.Connect();
    IdFTP1.Get('00001.m4a', TPath.GetDocumentsPath + PathDelim + '00001.m4a', True, False);
  except
    IdFTP1.Disconnect;
  end;
end;

procedure TForm1.IdFTP1AfterGet(ASender: TObject; AStream: TStream);
begin
  IdFTP1.Disconnect;
end;

procedure TForm1.IdFTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
  if FileExists(TPath.GetDocumentsPath + PathDelim + '00001.m4a') then
  begin
    ShowMessage('Downloaded!');
  end;
end;

Пример кода с потоком (не работает корректно):

uses ..., IdFTPCommon;

type
  TLoadThread = class(TThread)
  public
    constructor Create; reintroduce;
  protected
    procedure Execute; override;
  end;

type
  TForm1 = class(TForm)
  ...
  procedure ThreadTerminated(Sender: TObject);
  ...

var
  RecordDownload: TMemoryStream;
  Loading: Boolean = False;
  zLThread: TLoadThread = nil;

uses System.IOUtils;

constructor TLoadThread.Create;
begin
  inherited Create(True);
  FreeOnTerminate := True;
end;

procedure TLoadThread.Execute;
begin
  try
    Form1.IdFTP1.Connect();
    Form1.IdFTP1.Get('00001.m4a', TPath.GetDocumentsPath + PathDelim + '00001.m4a', True, False);
  except
    Form1.IdFTP1.Disconnect;
  end;
end;

procedure TForm1.ThreadTerminated(Sender: TObject);
begin
  zLThread := nil;
  Loading := False;
  FloatAnimation1.Enabled := False;
  FloatAnimation2.Enabled := False;
  Arc3.StartAngle := -90;
  Arc3.EndAngle := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  IdFTP1.Host := 'motoristaajudante.ddns.net';
  IdFTP1.Port := 2121;
  IdFTP1.DataPortMin := 50100;
  IdFTP1.DataPortMax := 51100;
  IdFTP1.Username := 'anonymous';
  IdFTP1.TransferType := IdFTPCommon.TIdFTPTransferType.ftBinary;
  IdFTP1.Passive := True;
  zLThread := TLoadThread.Create;
  zLThread.OnTerminate := ThreadTerminated;
  zLThread.Start;
  Loading := True;
  FloatAnimation1.Enabled := True;
  FloatAnimation2.Enabled := True;
end;

procedure TForm1.IdFTP1AfterGet(ASender: TObject; AStream: TStream);
begin
  IdFTP1.Disconnect;
end;

procedure TForm1.IdFTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
  Form1.FloatAnimation1.Enabled := False;
  Form1.FloatAnimation2.Enabled := False;
  Form1.Arc3.StartAngle := -90;
  Form1.Arc3.EndAngle := 0;
  if FileExists(TPath.GetDocumentsPath + PathDelim + '00001.m4a') then
  begin
    ShowMessage('Downloaded!');
  end;
end;

procedure TForm1.IdFTP1Status(ASender: TObject; const AStatus: TIdStatus; const AStatusText: string);
begin
  Memo1.Lines.Add(AStatusText);
  Application.ProcessMessages;
end;

Решение проблемы

При использовании потока для загрузки файлов с помощью IdFTP важно правильно обработать события и исключения. Indy является синхронной библиотекой, поэтому методы, такие как Get(), не возвращают управление до завершения загрузки. Если происходит ошибка, то выбрасывается исключение.

В примере кода без потока мы используем конструкцию try/finally для вызова Disconnect() и проверяем, не было ли исключения после вызова Get(). В примере кода с потоком мы также используем try/finally и обрабатываем исключения в методе Execute потока.

Кроме того, при работе с потоками важно синхронизировать доступ к UI-контролам. В примере кода с потоком мы используем событие OnTerminate потока для синхронизации доступа к UI-контролам.

Пример кода с потоком (работает корректно):

uses ..., IdFTPCommon;

type
  TLoadThread = class(TThread)
  public
    constructor Create; reintroduce;
  protected
    procedure Execute; override;
  end;

type
  TForm1 = class(TForm)
  ...
  procedure ThreadTerminated(Sender: TObject);
  ...

var
  RecordDownload: TMemoryStream;
  Loading: Boolean = False;
  zLThread: TLoadThread = nil;

uses System.IOUtils;

constructor TLoadThread.Create;
begin
  inherited Create(True);
  FreeOnTerminate := True;
end;

procedure TLoadThread.Execute;
begin
  Form1.IdFTP1.Connect;
  try
    Form1.IdFTP1.Get('00001.m4a', TPath.GetDocumentsPath + PathDelim + '00001.m4a', True, False);
  finally
    Form1.IdFTP1.Disconnect;
  end;
end;

procedure TForm1.ThreadTerminated(Sender: TObject);
begin
  zLThread := nil;
  Loading := False;
  FloatAnimation1.Enabled := False;
  FloatAnimation2.Enabled := False;
  Arc3.StartAngle := -90;
  Arc3.EndAngle := 0;
  If TThread(Sender).FatalException = nil then
    ShowMessage('Downloaded!')
  else
    ShowMessage('Error while Downloading!');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  IdFTP1.Host := 'motoristaajudante.ddns.net';
  IdFTP1.Port := 2121;
  IdFTP1.DataPortMin := 50100;
  IdFTP1.DataPortMax := 51100;
  IdFTP1.Username := 'anonymous';
  IdFTP1.TransferType := IdFTPCommon.TIdFTPTransferType.ftBinary;
  IdFTP1.Passive := True;
  zLThread := TLoadThread.Create;
  zLThread.OnTerminate := ThreadTerminated;
  zLThread.Start;
  Loading := True;
  FloatAnimation1.Enabled := True;
  FloatAnimation2.Enabled := True;
end;

procedure TForm1.IdFTP1Status(ASender: TObject; const AStatus: TIdStatus; const AStatusText: string);
begin
  TThread.Queue(nil,
    procedure
    begin
      Memo1.Lines.Add(AStatusText);
    end
  );
end;

При использовании потока для загрузки файлов с помощью IdFTP важно правильно обработать события и исключения, а также синхронизировать доступ к UI-контролам. В этом примере мы показали, как правильно использовать потоки для загрузки файлов с помощью IdFTP в Android на платформе Delphi.

Создано по материалам из источника по ссылке.

Проблема потоковой загрузки с IdFTP в Android на платформе Delphi решается правильной обработкой событий и исключений, а также синхронизацией доступа к UI-контролам.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: FTP ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 12:14:08/0.0054678916931152/1