CEF 文件下载功能实现

CEF 下载功能非常容易拓展,它提供了丰富的接口和控制功能,比如对正在下载的文件实现暂停、继续、取消等操作。并且 CEF 还帮我们默认实现了一个另存为的对话框,如果不是必须你甚至都不需要去自己实现这个保存对话框。接下来我们来看 CEF 对于下载功能提供的两个接口(使用 cefclient 项目举例)

继承 CefDownloadHandler

在一切开始之前,首先你的 ClientHandler 要继承 CefDownloadHandler 类:

该类提供了两个接口,分别是 OnBeforeDownloadOnDownloadUpdated,前者是在下载任务开始之前就会被回调的一个接口,你需要根据你的需求在该接口中实现一些预处理操作。后者是任务下载过程中的回调接口,包含了任务的进度、状态以及控制功能。下面分别详细介绍两个接口。

OnBeforeDownload 接口

virtual void OnBeforeDownload(
      CefRefPtr<CefBrowser> browser,
      CefRefPtr<CefDownloadItem> download_item,
      const CefString& suggested_name,
      CefRefPtr<CefBeforeDownloadCallback> callback) = 0;

上面介绍到该接口会在文件开始下载前被调用,

  • browser 参数表示当前实例
  • download_item 中包含了该下载任务的状态信息,可以通过其成员函数 IsInProgressIsCompleteIsCanceled 等方法判断文件的当前状态,但在下载文件之前去判断这些貌似没有什么意义。
  • suggested_name 代表当前 CEF 帮你设定好的建议保存名称,一般会截取文件路径中最后的文件名作为建议名称。
  • callback 这个参数比较重要,当你调用了 callback 的 Continue 方法后,任务就开始下载了,该回调第一个参数 download_path 就是保存文件的名称,第二个参数表示是否弹出保存对话框,当把第二个参数设置为 true 时,CEF 会帮我们弹出一个 Save File 的保存对话框。如果你设置为 false 了,那么将不弹出保存对话框,并自动保存文件到第一个参数设定的路径下。

通过该接口我们可以对任务做一些预处理,比如当你想在界面中创建一个下载任务时,可以通过 download_item 参数获得任务 ID(GetId 方法)交给 UI 去表示任务即将开始。接下来进入下面的下载任务状态更新函数时,再根据任务 Id 去更新界面内容。

OnDownloadUpdated 接口

该接口在任务下载过程中被回调,但据我测试,这个接口会优先于 OnBeforeDownload 接口被调用,具体原因还是不太了解,不过无伤大雅,我们只关注这里的任务进度、状态和控制功能就可以了。

virtual void OnDownloadUpdated(CefRefPtr<CefBrowser> browser,
                                 CefRefPtr<CefDownloadItem> download_item,
                                 CefRefPtr<CefDownloadItemCallback> callback) {}
  • browser 这个不多介绍了
  • download_item 与上面介绍的一样,可以获取任务的进度、状态、下载速度、已经下载量等,可以看一下 CefDownloadItem 的接口看一下都有什么控制功能。
  • callback 这里的 callback 和上面接口的 callback 是不一样的,这个 callback 可以控制任务的暂停、继续、停止等操作,你可以维护一份当前任务的列表将该 callback 与任务 Id 绑定,当界面传来暂停任务的控制消息时,可以通过任务 Id 到列表中找到这个 callback,调用 callback 的 Pause 方法来暂停任务。当然别忘记在任务完成或者被取消的时候从列表中移除这些 callback 和任务 Id 的绑定关系。

总结

CEF 提供的下载接口控制功能还是很丰富的,甚至将进度中下载的速度都帮你计算完成你可以直接使用的。如果想配合 UI 实现一些个性化的展示都是可以完成的。大家可以自己试一试,遇到任何技术问题欢迎在下方讨论。

CEF 文件下载功能实现》有7个想法

  1. qwe

    请问一下 当前任务的列表将该 callback 与任务 Id 绑定 这个具体怎么操作的?

    回复
    1. myCode 文章作者

      下载的任务有唯一标识的,以标识做 key,callback 做 value,状态更新时根据 key 查找 callback。

      回复
      1. 三蛋

        还想请教一下,callback.Pause()之后,如何获取状态更新?
        暂停后OnDownloadUpdated都不会进入了

        回复
        1. myCode 文章作者

          callback 要有缓存的,暂停状态你要自己维护同时配合 UI 展示,继续时去缓存中查找被暂停的任务 callback 恢复下载。

          回复
  2. 三蛋

    想请问一下,chrome内核可以通过ShowDevTools打开控制台,IE内核要怎么打开?

    回复
  3. happy!

    您好,问一下 我写了这些代码后,点击一个下载链接没有反应是怎么回事?
    是否要在主进程中声明?

    回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注