登录 用户中心() [退出] 后台管理 注册
   
您的位置: 首页 >> SoftHub关联区 >> 主题: Cef6 -- 下载支持[zt]     [回主站]     [分站链接]
Cef6 -- 下载支持[zt]
clq
浏览(251) - 2020-03-06 18:43:59 发表 编辑

关键字: cef


来自 http://www.freesion.com/article/903186554/

Cef6 -- 下载支持

标签: cef 下载 CefDownloadHandler

今天说一下CEF的下载模块,继承CefDownloadHandler模块,重写OnBeforeDownload和OnDownloadUpdated方法。第一篇已经讲过,CEF是一个封装的浏览器控件,以接口的形式封装,也就是CEF其实是多组接口函数的集合。CEF的开发是围绕接口的开发,所有行为的实现都需要继承相应的接口,重写对应的方法,达到修改默认行为的目的。

实现下载,遇到一些问题,CSDN的答案基本都没解决,CEF的论坛很强大,有你想要的答案,强力推荐一下。

http://magpcss.org/ceforum/viewtopic.php?t=12619

CEF开发,方法重写很重要的一点,如果返回false,一般代表使用CEF的默认行为处理这次事件,返回true代表自己重新定义了这次事件的行为。

继承和重写

所有的下载行为,对话框调用,右键菜单等行为都是用户行为,所以肯定在UI进程或者线程内处理。

class CustomClient : public CefClient
, public CefLifeSpanHandler
, public CefDisplayHandler
, public CefContextMenuHandler
, public CefDownloadHandler

void CustomClient::OnBeforeDownload(
CefRefPtr browser,
CefRefPtr download_item,
const CefString& suggested_name,
CefRefPtr callback)
{
// 这里需要传入需要保存文件的路径
CefString url = download_item->GetURL();
//std::string path = getDownloadPath(suggested_name);

callback->Continue("", true);
}

void CustomClient::OnDownloadUpdated(
CefRefPtr browser,
CefRefPtr download_item,
CefRefPtr callback)
{

if (download_item->IsComplete())
{
//MessageBox.Show("下载成功");
if (browser->IsPopup() && !browser->HasDocument())
{
//browser->GetHost()->ParentWindowWillClose();
browser->GetHost()->CloseBrowser(true);
}
}
}

OnBeforeDownload,可以控制当前下载是否要开启(继续)或者直接退出下载。

这里我同时继承了CefContextMenuHandler接口,重写其OnBeforeContextMenu和OnContextMenuCommand用来自定义右键菜单行为。同时继承CefLifeSpanHandler,重写其OnBeforePopup方法。为什么要继承额外这两个接口,下面分析一下CEF几种下载场景。

CEF下载的几种场景(同chrome浏览器的场景)

应用程序下载(或者压缩文件,镜像文件等无法在浏览器预览的文件)。CEF行为是直接弹出另存为对话框,选择路径,然后回传下载状态,到下载结束。

PDF文件下载。(firefox 和chrome对PDF文件提供在线浏览功能)内部定制了pdf的行为。

图片下载。在线预览,默认不支持下载。

CEF默认的下载行为是popup新的进程窗口(多进程模式下),在该进程中处理下载行为,这种方式会有白屏的问题,下面会重点讲。

解决下载页弹出空白窗口的问题

触发下载,CEF默认会调用CefLifeSpanHandler接口的OnBeforePopup方法中。我们在这里拦截到请求就可以做定制了。

bool CustomClient::OnBeforePopup(CefRefPtr browser, CefRefPtr frame, const CefString& target_url, const CefString& target_frame_name, WindowOpenDisposition target_disposition, bool user_gesture, const CefPopupFeatures& popupFeatures, CefWindowInfo& windowInfo, CefRefPtr& client, CefBrowserSettings& settings, bool* no_javascript_access)
{
switch (target_disposition)
{
case WOD_NEW_FOREGROUND_TAB:
case WOD_NEW_BACKGROUND_TAB:
case WOD_NEW_POPUP:
case WOD_NEW_WINDOW:

if (!target_url.empty())
{
browser->GetHost()->StartDownload(target_url);
}
//browser->GetMainFrame()->LoadURL(target_url);
return true; //cancel create
}

return false;
}

如果默认返回false,就会出现上面白屏的情况(非异常,但是有个多余的浏览器进程被创建了)。所以这里对几种模式做了过滤,禁止CEF弹出新的浏览器窗口,转而在当前浏览器加载要跳转的界面,处理如下

browser->GetMainFrame()->LoadURL(target_url);

效果见截图(这里其实有三种情况,对应三种下载场景),直接在当前浏览器页面打开另存为对话框



对于PDF和图片,效果如下,这是CEF默认的定制化的PDF在线浏览行为,同chrome浏览器打开,而且也支持下载、打印



再看下图片,图片支持比较差,默认只提供了在线预览,无法直接下载,见下图

定制右键菜单,实现图片下载

所以上文的CefContextMenuHandler接口就是用来做这个工作。然后重写,新增菜单项,然后绑定响应的时间。菜单如果是中文需要转成utf8或者utf16\32等格式,否则乱码。菜单ID处理如下

void CustomClient::OnBeforeContextMenu(CefRefPtr browser, CefRefPtr frame, CefRefPtr params, CefRefPtr model)
{
std::wstring wstr(L"另存为");
CefString strTitle("");
strTitle = unicode2Utf8(wstr.c_str());

CefString url = params->GetSourceUrl();
model->AddItem(CLIENT_ID_SHOW_DOWNLOAD_IMAGE, strTitle);

//model->Clear();
}

bool CustomClient::OnContextMenuCommand(CefRefPtr browser, CefRefPtr frame, CefRefPtr params, int command_id, EventFlags event_flags)
{
CEF_REQUIRE_UI_THREAD();

switch (command_id) {
case CLIENT_ID_SHOW_DOWNLOAD_IMAGE:
browser->GetHost()->StartDownload(params->GetSourceUrl());//DownloadImage(params->GetSourceUrl());
return true;
default: // Allow default handling, if any.
//return ExecuteTestMenu(command_id);
break;
}
return false;
}

enum client_menu_ids {
CLIENT_ID_SHOW_DOWNLOAD_IMAGE = MENU_ID_USER_FIRST,
};

触发下载操作,找了很久都没找到,最后还是在CEF论坛找到的,一共有两种方法触发下载操作

browser->GetHost()->StartDownload(params->GetSourceUrl());//DownloadImage(params->GetSourceUrl());

browser->GetHost()->DownloadImage(params->GetSourceUrl());

而且都是在browser host 上的操作。这个优劣没有比较过,上面的方法只需要传入下载的url 就可以触发下载操作,但貌似下载的中间过程无法知道(下载进度,下载速度,何时下载完成等),下面的要传入四个参数, 所以上面的中间状态全都可以获取到,貌似还可以处理缓存,可以限制图片大小等,具体没有试,这里就不瞎说了。

到这里下载和预览都支持了。最后再说一下,如何屏蔽预览和右键菜单,下载直接触发另存为操作。

屏蔽右键菜单,只需要在OnBeforeContextMenu中把model清空,见上面注释。

屏蔽预览,直接触发下载操作。同样OnBeforePopup,不加载url, 直接调用下载操作,见上面实现部分。

好了,到这里使用CEF对下载做一些定制化操作就将完了。明天见。


总数:0 页次:1/0 首页 尾页  
总数:0 页次:1/0 首页 尾页  


所在合集/目录



发表评论:
文本/html模式切换 插入图片 文本/html模式切换


附件:



NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.

Copyright © 2005-2020 clq, All Rights Reserved
版权所有
桂ICP备15002303号-1