首先感谢:http://blog.csdn.net/foruok/article/details/50679694
经过此文章的详细说明,我成功实现了cef独立于浏览器的http请求和对reponse的处理。我的初衷是通过http的get请求缓存所有请求过的页面到本地。
以下是我的代码UrlRequestClass.h:
#ifndef URL_REQUEST_CLIENT_H
#define URL_REQUEST_CLIENT_H
#include "include/wrapper/cef_helpers.h"
#include "include/cef_urlrequest.h"
#include
#include
#pragma comment(lib, "urlmon.lib")
class UrlRequestCompletionCallback
{
public:
virtual ~UrlRequestCompletionCallback(){}
virtual void OnCompletion(CefURLRequest::ErrorCode errorCode,
const std::string& data) = 0;
};
class UrlRequestClass :public CefURLRequestClient
{
public:
UrlRequestClass();
void OnRequestComplete(CefRefPtr request) OVERRIDE;
void OnUploadProgress(CefRefPtr request,
int64 current,
int64 total) OVERRIDE;
void OnDownloadProgress(CefRefPtr request,
int64 current,
int64 total) OVERRIDE;
void OnDownloadData(CefRefPtr request,
const void* data,
size_t data_length) OVERRIDE;
bool GetAuthCredentials(bool isProxy,
const CefString& host,
int port,
const CefString& realm,
const CefString& scheme,
CefRefPtr callback) OVERRIDE{
return false;
}
void Request(CefRefPtr cef_request);
void Get(const std::string &url, const CefRequest::HeaderMap &headers = CefRequest::HeaderMap());
void Post(const std::string &url, const CefRefPtr data, const CefRequest::HeaderMap &headers = CefRequest::HeaderMap());
void SetCompletionCallback(UrlRequestCompletionCallback *callback);
private:
CefRefPtr m_urlRequest;
std::string m_data;
std::ofstream *pfile;
CRITICAL_SECTION m_cs;// = NULL;
IMPLEMENT_REFCOUNTING(UrlRequestClass);
DISALLOW_COPY_AND_ASSIGN(UrlRequestClass);
};
#endif
说明:
UrlRequestClass.cpp文件
#include "UrlRequestClass.h"
#include
#include
#include
#include
UrlRequestClass::UrlRequestClass()
{
CEF_REQUIRE_UI_THREAD();
pfile = new std::ofstream();
pfile->rdbuf()->pubsetbuf(0, 0);
pfile->open("C:\\Users\\ffmpeg.zip", std::ios::app | std::ios::out | std::ios::binary);//文件路径+后缀
}
void UrlRequestClass::OnRequestComplete(CefRefPtr request)
{
CEF_REQUIRE_UI_THREAD();
pfile->close();
}
void UrlRequestClass::OnUploadProgress(CefRefPtr request, int64 current, int64 total)
{
}
void UrlRequestClass::OnDownloadProgress(CefRefPtr request, int64 current, int64 total)
{
char szLog[128] = { 0 };
sprintf_s(szLog, 128, "UrlRequestClass::OnDownloadProgress, current-%lld, total-%lld\r\n",
current, total);
OutputDebugStringA(szLog);
}
void UrlRequestClass::OnDownloadData(CefRefPtr request, const void* data, size_t data_length)
{
CEF_REQUIRE_UI_THREAD();
m_data += std::string(static_cast(data), data_length);
if (data_length>0)
{
std::stringstream filstream;
filstream.write((char *)data, data_length);
pfile->write(filstream.str().c_str(), data_length);
}
}
void UrlRequestClass::Request(CefRefPtr cef_request)
{
m_urlRequest = CefURLRequest::Create(cef_request, this, NULL);
}
void UrlRequestClass::Get(const std::string &url, const CefRequest::HeaderMap &headers)
{
CefRefPtr req = CefRequest::Create();
req->SetURL(url);
req->SetMethod("GET");
req->SetHeaderMap(headers);
Request(req);
}
void UrlRequestClass::Post(const std::string &url, const CefRefPtr data, const CefRequest::HeaderMap &headers)
{
CefRefPtr req = CefRequest::Create();
req->SetURL(url);
req->SetMethod("POST");
req->SetHeaderMap(headers);
req->SetPostData(data);
Request(req);
}
void UrlRequestClass::SetCompletionCallback(UrlRequestCompletionCallback *callback)
{
}
应用,在cefclient_win.cc的context的初始化之后调用:
UrlRequestClass test;
test.Get("https://ffmpeg.zeranoe.com/builds/win32/dev/ffmpeg-20180207-8318bf1-win32-dev.zip");
这是ffmpeg的压缩包,成功下载解压。
另外:说明一个我在写这个的过程中踩过很多次的坑:
这是我原先的文件读写函数
if (data_length>0)
{
std::ofstream pfile;
std::stringstream filstream;
filstream.write((char *)data, data_length);
pfile.rdbuf()->pubsetbuf(0, 0);
pfile.open("C:\\Users\\qqtest.exe", std::ios::app | std::ios::out | std::ios::binary);
if (false == pfile.is_open())
{
pfile.close();
OnDownloadData(request, data, data_length);
//这两句原先是MessageBox(NULL,NULL,NULL,NULL);
}
pfile.write(filstream.str().c_str(), data_length);
pfile.close();
}
上面是每写一部分数据都要打开关闭文件一次,后果是除了图片格式,其他的文档如:.exe .zip .doc .mp4文件下载后打开时都会出现部分数据丢失/破损的提示,多次调试发现原因是文件被其他进程打开占。
后来改为在构造函数中打开文件,中间一直写文件直到写完再关闭,解决了数据丢失的问题。
文件操作这里还是值得注意的!!!