构建windows桌面应用程序,使用cef3框架,其中实现加载本地资源方式为zip压缩包的形式(同样的方式也可以做成动态库形式,或者直接以win32资源加载的形式)。
具体实现如下:
实现自己的provider
class PcmBinaryResourceProvider : public CefResourceManager::Provider {
public:
explicit PcmBinaryResourceProvider(const std::string& url_path)
: url_path_(url_path) {
DCHECK(!url_path.empty());
}
bool OnRequest(scoped_refptr
{
CEF_REQUIRE_IO_THREAD();
const std::string& url = request->url();
if (url.find(url_path_) != 0L) {
// Not handled by this provider.
return false;
}
CefRefPtr
const std::string& relative_path = url.substr(url_path_.length());
if (!relative_path.empty()) {
CefRefPtr
GetBinaryResourceReader(relative_path.data());
if (stream.get()) {
handler = new CefStreamResourceHandler(
request->mime_type_resolver().Run(url),
stream);
}
}
request->Continue(handler);
return true;
}
private:
std::string url_path_;
DISALLOW_COPY_AND_ASSIGN(PcmBinaryResourceProvider);
};
CefResourceManager::Provider* CreatePcmBinaryResourceProvider(
const std::string& url_path)
{
return new PcmBinaryResourceProvider(url_path);
}
最后在test_runner.cc中添加(标红字段):
void SetupResourceManager(CefRefPtr
if (!CefCurrentlyOn(TID_IO)) {
// Execute on the browser IO thread.
CefPostTask(TID_IO, base::Bind(SetupResourceManager, resource_manager));
return;
}
const std::string& test_origin = kTestOrigin;
// Add the URL filter.
resource_manager->SetUrlFilter(base::Bind(RequestUrlFilter));
// Add provider for resource dumps.
resource_manager->AddProvider(
new RequestDumpResourceProvider(test_origin + "request.html"), 0,
std::string());
// Add provider for bundled resource files.
#if defined(OS_WIN)
// Read resources from the binary.
//resource_manager->AddProvider(
// CreateBinaryResourceProvider(test_origin, std::string()), 100,
// std::string());
const std::string& pcm_origin = kPcmOrigin;
resource_manager->AddProvider(CreatePcmBinaryResourceProvider(pcm_origin),
100, std::string());
#elif defined(OS_POSIX)
// Read resources from a directory on disk.
std::string resource_dir;
if (GetResourceDir(resource_dir)) {
resource_manager->AddDirectoryProvider(test_origin, resource_dir, 100,
std::string());
}
#endif
}
完整如下
CuiResRequest.cpp
#include "stdafx.h"
#include "CuiResRequest.h"
#include "include/base/cef_logging.h"
#include "include/cef_stream.h"
#include "include/wrapper/cef_byte_read_handler.h"
#include "include/wrapper/cef_stream_resource_handler.h"
#include "XUnzip.cpp"
#include
#define CUI_RESTYPE_FILE
#define ZIP_REALATIVE_PATH L"skin\\dist\\dist.pak"
#define LOCALFILEFLAG "file:///"
typedef struct {
DWORD dwsize;
LPBYTE pBytes;
}ResouseInfo;
std::map
static char CharToInt(char ch)
{
if (ch >= '0' && ch <= '9')return (char)(ch - '0');
if (ch >= 'a' && ch <= 'f')return (char)(ch - 'a' + 10);
if (ch >= 'A' && ch <= 'F')return (char)(ch - 'A' + 10);
return -1;
}
static char StrToBin(char *str)
{
char tempWord[2];
char chn;
tempWord[0] = CharToInt(str[0]); //make the B to 11 -- 00001011
tempWord[1] = CharToInt(str[1]); //make the 0 to 0 -- 00000000
chn = (tempWord[0] << 4) | tempWord[1]; //to change the BO to 10110000
return chn;
}
std::string URLDecodeToAscii(const std::string str)
{
std::string inputstr = str;
std::string output = "";
char tmp[2];
int i = 0, idx = 0, len = inputstr.length();
while (i < len) {
if (inputstr[i] == '%') {
tmp[0] = inputstr[i + 1];
tmp[1] = inputstr[i + 2];
output += StrToBin(tmp);
i = i + 3;
}
else if (inputstr[i] == '+') {
output += ' ';
i++;
}
else {
output += inputstr[i];
i++;
}
}
if (!output.empty())
{
//utf-8 ---> unicode
int unicodeLen = MultiByteToWideChar(CP_UTF8, 0, output.c_str(), -1, nullptr, 0);
wchar_t *pUnicode = (wchar_t*)malloc(sizeof(wchar_t)*unicodeLen);
MultiByteToWideChar(CP_UTF8, 0, output.c_str(), -1, pUnicode, unicodeLen);
//unicode ---> ascii
int ansiiLen = WideCharToMultiByte(CP_ACP, 0, pUnicode, -1, nullptr, 0, nullptr, nullptr);
std::string filepath(ansiiLen, 0);
WideCharToMultiByte(CP_ACP, 0, pUnicode, -1, &filepath[0], ansiiLen, nullptr, nullptr);
return filepath;
}
return output;
}
class PcmBinaryResourceProvider : public CefResourceManager::Provider {
public:
explicit PcmBinaryResourceProvider(const std::string& url_path)
: url_path_(url_path) {
DCHECK(!url_path.empty());
}
bool OnRequest(scoped_refptr
{
CEF_REQUIRE_IO_THREAD();
const std::string& url = request->url();
if (url.find(url_path_) != 0L) {
// Not handled by this provider.
return false;
}
CefRefPtr
const std::string& relative_path = url.substr(url_path_.length());
if (!relative_path.empty()) {
CefRefPtr
GetBinaryResourceReader(relative_path.data());
if (stream.get()) {
handler = new CefStreamResourceHandler(
request->mime_type_resolver().Run(url),
stream);
}
}
request->Continue(handler);
return true;
}
private:
std::string url_path_;
DISALLOW_COPY_AND_ASSIGN(PcmBinaryResourceProvider);
};
std::string GetAppPathA()
{
std::string strPath;
char szBuffer[MAX_PATH] = { 0 };
::GetModuleFileNameA(NULL, szBuffer, MAX_PATH);
strPath = szBuffer;
int nFind = strPath.find_last_of('\\');
return strPath.substr(0, nFind + 1);
}
std::wstring GetAppPathW()
{
std::wstring strPath;
wchar_t szBuffer[MAX_PATH] = { 0 };
::GetModuleFileNameW(NULL, szBuffer, MAX_PATH);
strPath = szBuffer;
int nFind = strPath.find_last_of('\\');
return strPath.substr(0, nFind + 1);
}
bool LoadResourceFromMemory(const char* resource_name, DWORD &dwSize, LPBYTE &pBytes)
{
if (map_resource.empty())
{
return false;
}
std::map
for (; it != map_resource.end(); ++it)
{
if (0 == strcmp(resource_name, it->first.c_str()))
{
dwSize = it->second.dwsize;
pBytes = it->second.pBytes;
return true;
}
}
return false;
}
bool LoadResourceFromFile(const char* resource_name, bool isfullpath, DWORD &dwSize, LPBYTE &pBytes)
{
FILE* fp = nullptr;
std::string urlPath;
if (!isfullpath)
{
urlPath = GetAppPathA();
urlPath += resource_name;
}
else
{
urlPath = resource_name;
}
fopen_s(&fp, urlPath.c_str(), "rb");
if (nullptr == fp)
{
return false;
}
fseek(fp, 0, SEEK_END);
long filesize = ftell(fp);
rewind(fp);
pBytes = (LPBYTE)malloc(sizeof(char) * (filesize + 1));
ZeroMemory(pBytes, sizeof(char) * (filesize + 1));
size_t count = fread(pBytes, 1, filesize, fp);
dwSize = count;
ResouseInfo ResInfo;
ResInfo.dwsize = dwSize;
ResInfo.pBytes = pBytes;
map_resource.insert(std::pair
return true;
}
bool LoadResourceFromZip(const char* resource_name, DWORD &dwSize, LPBYTE &pBytes)
{
std::wstring ZipPath = GetAppPathW();
ZipPath += ZIP_REALATIVE_PATH;
static HZIP hZip = nullptr;
if (nullptr == hZip)
{
hZip = OpenZipU((void*)ZipPath.c_str(), 0, ZIP_FILENAME);
}
if (nullptr == hZip)
{
return false;
}
int unicodeLen = MultiByteToWideChar(CP_UTF8, 0, resource_name, -1, nullptr, 0);
wchar_t *pUnicode = (wchar_t*)malloc(sizeof(wchar_t)*unicodeLen);
MultiByteToWideChar(CP_UTF8, 0, resource_name, -1, pUnicode, unicodeLen);
int index;
ZIPENTRYW ze;
ZRESULT zRet = FindZipItemW(hZip, pUnicode, true, &index, &ze);
if (zRet != ZR_OK)
{
return false;
}
zRet = GetZipItemW(hZip, index, &ze);
if (zRet != ZR_OK)
{
return false;
}
pBytes = (LPBYTE)malloc(ze.unc_size);
ZeroMemory(pBytes, ze.unc_size);
zRet = UnzipItem(hZip, index, pBytes, ze.unc_size, ZIP_MEMORY);
if (zRet != 0x00000000 && zRet != 0x00000600) {
free(pUnicode);
return false;
}
dwSize = ze.unc_size;
ResouseInfo ResInfo;
ResInfo.dwsize = dwSize;
ResInfo.pBytes = pBytes;
map_resource.insert(std::pair
free(pUnicode);
return true;
}
#if 0
bool LoadResourceFromFileEx(std::string resource_name, DWORD &dwSize, LPBYTE &pBytes)
{
FILE* fp = nullptr;
fopen_s(&fp, resource_name.c_str(), "rb");
if (nullptr == fp)
{
int num = GetLastError();
return false;
}
fseek(fp, 0, SEEK_END);
long filesize = ftell(fp);
rewind(fp);
pBytes = (LPBYTE)malloc(sizeof(char) * (filesize + 1));
ZeroMemory(pBytes, sizeof(char) * (filesize + 1));
size_t count = fread(pBytes, 1, filesize, fp);
dwSize = count;
ResouseInfo ResInfo;
ResInfo.dwsize = dwSize;
ResInfo.pBytes = pBytes;
map_resource.insert(std::pair
return true;
}
#endif
bool LoadBinaryResource(const char* resource_name, DWORD &dwSize, LPBYTE &pBytes)
{
if (LoadResourceFromMemory(resource_name, dwSize, pBytes))
{
return true;
}
std::string strFileFlag = resource_name;
std::string temp = strFileFlag.substr(0, 8);
std::string flag = LOCALFILEFLAG;
if (strcmp(temp.c_str(), flag.c_str()) == 0)
{
strFileFlag = strFileFlag.substr(8);
return LoadResourceFromFile(strFileFlag.c_str(), true, dwSize, pBytes);
}
#ifdef CUI_RESTYPE_FILE
return LoadResourceFromFile(resource_name, false, dwSize, pBytes);
#else
return LoadResourceFromZip(resource_name, dwSize, pBytes);
#endif
}
CefRefPtr
if (nullptr == resource_name)
{
return nullptr;
}
DWORD dwSize;
LPBYTE pBytes;
std::string filepath = URLDecodeToAscii(resource_name);
if (LoadBinaryResource(filepath.c_str(), dwSize, pBytes)) {
return CefStreamReader::CreateForHandler(
new CefByteReadHandler(pBytes, dwSize, NULL));
}
//TODO:如果资源没找到,不做任何处理
//NOTREACHED(); // The resource should be found.
return NULL;
}
CefResourceManager::Provider* CreatePcmBinaryResourceProvider(
const std::string& url_path)
{
return new PcmBinaryResourceProvider(url_path);
}
bool LoadBinaryResource(const char* resource_name, std::string& resource_data)
{
DWORD dwSize;
LPBYTE pBytes;
if (!LoadBinaryResource(resource_name, dwSize, pBytes))
{
return false;
}
std::string strTemp(dwSize, 0);
memcpy_s(&strTemp[0], dwSize, pBytes, dwSize);
resource_data = strTemp;
return true;
}
CuiResRequest.h
#pragma once
#include
#include "include/wrapper/cef_resource_manager.h"
bool LoadBinaryResource(const char* resource_name, std::string& resource_data);
CefRefPtr
CefResourceManager::Provider* CreatePcmBinaryResourceProvider(
const std::string& url_path);