CEF独立于浏览器的http请求

3 篇文章 0 订阅
1 篇文章 0 订阅

首先感谢: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 <string>
#include <UrlMon.h>
#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<CefURLRequest> request) OVERRIDE;

	void OnUploadProgress(CefRefPtr<CefURLRequest> request,
		int64 current,
		int64 total) OVERRIDE;

	void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
		int64 current,
		int64 total) OVERRIDE;

	void OnDownloadData(CefRefPtr<CefURLRequest> 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<CefAuthCallback> callback) OVERRIDE{
		return false;
	}

	void Request(CefRefPtr<CefRequest> cef_request);
	void Get(const std::string &url, const CefRequest::HeaderMap &headers = CefRequest::HeaderMap());
	void Post(const std::string &url, const CefRefPtr<CefPostData> data, const CefRequest::HeaderMap &headers = CefRequest::HeaderMap());

	void SetCompletionCallback(UrlRequestCompletionCallback *callback);
private:
	CefRefPtr<CefURLRequest> m_urlRequest;
	std::string m_data;
	std::ofstream *pfile;
	CRITICAL_SECTION m_cs;// = NULL;
	IMPLEMENT_REFCOUNTING(UrlRequestClass);
	DISALLOW_COPY_AND_ASSIGN(UrlRequestClass);
};

#endif

说明:

  • 请求必须在UI线程,所以构造函数有CEF_REQUIRE_UI_THREAD();
  • OnRequestComplete()是请求返回并处理成功之后的回调函数;
  • OnUploadProgress()是有上传文件时可计算当前上传进度的回调函数;
  • OnDownloadProgress()是下载文件时的下载进度回调;
  • OnDownloadData()是下载文件时调用的函数,要下载文件则需要手动填补此函数;
  • Request()函数发送封装好的Http请求;
  • Post()和Get()封装对应的请求、参数等;
  • SetCompletionCallback()设置完成请求之后的回调,在OnRequestComplete()之后触发。

UrlRequestClass.cpp文件

#include "UrlRequestClass.h"
#include <Windows.h>
#include <iostream>
#include <fstream>
#include <urlmon.h>

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<CefURLRequest> request)
{
	CEF_REQUIRE_UI_THREAD();
	pfile->close();
}

void UrlRequestClass::OnUploadProgress(CefRefPtr<CefURLRequest> request, int64 current, int64 total)
{

}

void UrlRequestClass::OnDownloadProgress(CefRefPtr<CefURLRequest> 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<CefURLRequest> request, const void* data, size_t data_length)
{
	CEF_REQUIRE_UI_THREAD(); 
	m_data += std::string(static_cast<const char*>(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<CefRequest> cef_request)
{
	m_urlRequest = CefURLRequest::Create(cef_request, this, NULL);
}

void UrlRequestClass::Get(const std::string &url, const CefRequest::HeaderMap &headers)
{
	CefRefPtr<CefRequest> req = CefRequest::Create();
	req->SetURL(url);
	req->SetMethod("GET");
	req->SetHeaderMap(headers);
	Request(req);
}

void UrlRequestClass::Post(const std::string &url, const CefRefPtr<CefPostData> data, const CefRequest::HeaderMap &headers)
{
	CefRefPtr<CefRequest> 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文件下载后打开时都会出现部分数据丢失/破损的提示,多次调试发现原因是文件被其他进程打开占。

后来改为在构造函数中打开文件,中间一直写文件直到写完再关闭,解决了数据丢失的问题。

文件操作这里还是值得注意的!!!


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CefSharp是一个使用C#编写的基于Google Chromium项目的开源项目,用于在.NET应用程序中集成浏览器功能。它提供了一个简单易用的方式来创建和定制一个功能强大的浏览器应用。 通过使用CefSharp,我们可以轻松地创建一个具备浏览器功能的自定义应用程序。可以将它集成到Windows桌面应用、ASP.NET网页、WPF应用等各种.NET项目中。 使用CefSharp制作浏览器有许多好处。首先,它可以为我们提供一个更强大的浏览器功能,包括支持HTML5、CSS3、JavaScript以及许多其他现代网络技术。这使得我们能够为用户提供一个与主流浏览器相似的体验。 其次,CefSharp具有强大的自定义能力。我们可以根据自己的需求进行修改和定制,包括更改浏览器外观、添加或删除功能等。这为我们提供了很大的灵活性,可以根据不同的项目需求进行个性化的定制。 此外,CefSharp提供了一系列的API和事件,使得我们能够与浏览器进行交互。我们可以通过代码控制浏览器的导航、加载特定的网页内容、执行JavaScript代码等。这让我们能够更好地控制和管理浏览器行为,实现更复杂的功能。 最后,CefSharp是一个活跃的开源项目,拥有一个庞大的社区支持。我们可以从社区中获取到许多有用的资源、文档和代码示例,以便更好地使用和了解CefSharp。 总之,使用CefSharp制作浏览器可以为我们提供强大的浏览器功能、灵活的定制能力、丰富的交互方式以及活跃的社区支持。这使得我们能够创建出功能丰富、用户友好的浏览器应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值