delphi System.Net.HttpClient后台进行非阻塞下载文件  
官方Delphi 学习QQ群: 682628230(三千人)
频道

delphi System.Net.HttpClient后台进行非阻塞下载文件


在我的过程系列中,我向您展示了如何在后台进行非阻塞处理。这是一个实际案例:从 Internet 下载文件。


在开发链接到第三方网站或 API 的移动应用程序或办公应用程序时,必须访问远程文件的情况并不少见。下载它们的最简单方法是使用 System.Net.HttpClient 单元的组件执行 GET。 


这是一个允许从 URL 检索文件并将其存储在本地的类。


unit u_download;


interface


uses system.SysUtils;


type

  tdownload_file = class(tobject)

    class procedure download(from_url, to_filename: string;

      success: tproc = nil; error: tproc = nil);

    class function temporaryFileName(appName: string): string;

  end;


implementation


{ download_file }


uses system.ioutils, system.Net.HttpClient, system.Classes;


class procedure tdownload_file.download(from_url, to_filename: string;

  success: tproc = nil; error: tproc = nil);

begin

  tthread.CreateAnonymousThread(

    procedure

    var

      serveur: THTTPClient;

      serveur_reponse: IHTTPResponse;

      fichier: tfilestream;

    begin

      try

        serveur := THTTPClient.Create;

        try

          serveur_reponse := serveur.Get(from_url);

          if serveur_reponse.StatusCode = 200 then

          begin

            fichier := tfilestream.Create(to_filename,

              fmCreate or fmOpenWrite or fmShareDenyWrite);

            try

              fichier.CopyFrom(serveur_reponse.ContentStream,

                serveur_reponse.ContentStream.Size);

            finally

              fichier.Free;

            end;

            if assigned(success) then

              tthread.queue(nil,

                procedure

                begin

                  success;

                end);

          end

          else

          begin

            raise Exception.CreateFmt

              ('Cannot get distant file. Please contact us or retry later. HTTP %d - %s',

              [serveur_reponse.StatusCode, serveur_reponse.StatusText]);

          end;

        finally

          serveur.Free;

        end;

      except

        if assigned(error) then

          tthread.queue(nil,

            procedure

            begin

              error;

            end);

      end;

    end).Start;

end;


class function tdownload_file.temporaryFileName(appName: string): string;

begin

  result := tpath.Combine(tpath.gettempPath,

    appName + '-' + datetimetotimestamp(now).Time.ToString + '.tmp')

end;


end.

由于我们想知道下载的结果,尤其是在下载结束时,还有什么比在必要时还要执行将调用的过程更好的呢?


因此,调用如下:


procedure TForm1.Button1Click(Sender: TObject);

begin

  Button1.Enabled := false;

  tdownload_file.download('http://gamolf.fr/images/gamolf-500x500.png',

    tpath.Combine(tpath.GetDocumentsPath(), '__monimage.png'),

    procedure

    begin

      showMessage('Fichier téléchargé');

      Button1.Enabled := true;

    end,

    procedure

    begin

      showMessage('Erreur lors du téléchargement');

      Button1.Enabled := true;

    end);

end;

在这个例子中,我只是在一个空表单上放置了一个 TButton。此按钮的 onclick 事件链接到 Button1Click 方法。该单元使用另外两个单元:用于下载的 u_download 和 System.IOUtils,其类 TPath 允许根据运行程序的平台获取有用文件列表。


当按钮被点击时,它被停用以防止它再次被点击,直到操作完成,然后调用指定 URL 的图像(这里是我的一个站点的标志)和本地存储文件夹的下载。此调用还传递两个匿名过程。在这些过程中,会显示警告用户传输状态,并且按钮状态会重新激活。


在这里,重新激活按钮是没有用的,因为再次单击它会下载相同的文件,但您可以看到原理。


当下载成功完成时,将调用作为参数传递的第一个过程。在发生错误时调用第二个:当引发异常时或者如果存在除 200 以外的 HTTP 错误代码,因为在这种情况下我们自己引发了异常。


它们在主进程中执行,因此提供对图形功能的访问,例如可视化组件或对话框。


注意他们的调用是如何在源中处理的:


class procedure tdownload_file.download(from_url, to_filename: string;

  success: tproc = nil; error: tproc = nil);

我们首先在进行下载的方法中声明两个类型为 TProc 的参数,如果未指定参数,我们将它们默认设置为 nil。确实可能发生在成功或错误的情况下我们无所事事,让最终的程序员选择是否使用它们。请注意,如果您想使用错误函数而不是成功函数,您仍然必须将参数传递给 nil,因为编译器将无法猜测您要跳过此参数。


当我们要调用它们时,我们测试是否指示了参数。assigned () 方法允许您知道某个指针是否指向某处,但不一定知道该某处是否有效,因此请注意并记住在释放对象时使用 FreeAndNil (myObjet) 而不仅仅是 myObjet.Free () 。最后,我们通过TThread.Queue()方法在提交给主线程的过程中调用成功或错误过程。


if assigned(success) then

  tthread.queue(nil,

procedure

begin

  success;

end);

这样就获得了一个代码,它可以在不中断程序运行的情况下简单地下载任何远程文件,同时能够在下载结束时采取行动。



推荐分享
图文皆来源于网络,内容仅做公益性分享,版权归原作者所有,如有侵权请告知删除!
 

Copyright © 2014 DelphiW.com 开发 源码 文档 技巧 All Rights Reserved
晋ICP备14006235号-8 晋公网安备 14108102000087号

执行时间: 0.047801971435547 seconds