Загрузка локального контента в Awesomium

Я написал локальный источник данных, потому что из того, что я знаю, нет ни одного, включенного в Awesomium, но дело в том, что он запрашивает все из источника данных html, изображений и т. Д.
И я понятия не имею, как я должен загружать все типы форматов MIME.
Мой текущий код поддерживает только html / text, где я загружаю файл в двоичный файл и отправляю как ответ. Это не работает для изображений.

Кто-нибудь знает, куда мне идти дальше?

class LocalDataSource :
public Awesomium::DataSource
{
public:
LocalDataSource() { }
virtual ~LocalDataSource() { }

virtual void OnRequest(int request_id, const Awesomium::WebString& path)
{
std::string filepath = Awesomium::ToString(path).insert(0, "./");
std::basic_ifstream<char> is(filepath, std::ios_base::in | std::ios_base::binary);
if (is)
{
is.seekg(0, is.end);
int length = is.tellg();
is.seekg(0, is.beg);

char *buffer = new char[length + 1];
is.read(buffer, length);
buffer[length] = '\0';
is.close();

SendResponse(request_id, strlen(buffer), (unsigned char*)buffer, Awesomium::WSLit("text/html"));
delete[] buffer;
}
else
{
// Error
}
}
};

РЕДАКТИРОВАТЬ:

сейчас я буду загружать файл относительно исполняемого файла и не буду использовать DataSource.

1

Решение

Я знаю, что это старое, но это было важно для меня, я исправил это так же, как Стивен, я опубликую код C ++, который я использовал:

bool ResInterceptor::OnFilterNavigation(int origin_process, int origin_routing_id, const Awesomium::WebString& method, const Awesomium::WebURL& url, bool is_main_frame)
{
return false;
}

Awesomium::ResourceResponse* ResInterceptor::OnRequest(Awesomium::ResourceRequest* request)
{
bool isAsset = std::strcmp(ToString(request->url().scheme()).c_str(), "asset")==0;
bool isFile = std::strcmp(ToString(request->url().scheme()).c_str(), "file")==0;

if(!isAsset && !isFile)
{
//if it is neither of these we "may" still intercept the call, this allows for offline-online versions to work
return Awesomium::ResourceInterceptor::OnRequest(request);
}

if(isAsset)
{
//Blah blah, do whatever
}
else if(isFile)
{
//Blah blah, same
}

//As you can see this isn't very, but it worked for my purposes
std::string contentpath = "E:/Location/of/files" + ToString(request->url().path());

Awesomium::WebString datatype;
std::string filename = Awesomium::ToString(request->url().filename());

//I still want to check for the correct mime type
if     (has_suffix(filename, ".html")) datatype = Awesomium::WSLit("text/html");
else if(has_suffix(filename, ".js"))   datatype = Awesomium::WSLit("text/javascript");
else if(has_suffix(filename, ".css"))  datatype = Awesomium::WSLit("text/css");
else if(has_suffix(filename, ".swf"))  datatype = Awesomium::WSLit("application/x-shockwave-flash");
else if(has_suffix(filename, ".zip"))  datatype = Awesomium::WSLit("application/zip");
else if(has_suffix(filename, ".txt"))  datatype = Awesomium::WSLit("text/plain");
else if(has_suffix(filename, ".text")) datatype = Awesomium::WSLit("text/plain");
else if(has_suffix(filename, ".png"))  datatype = Awesomium::WSLit("image/png");
else if(has_suffix(filename, ".jpeg")) datatype = Awesomium::WSLit("image/jpeg");
else if(has_suffix(filename, ".jpg"))  datatype = Awesomium::WSLit("image/jpeg");
else if(has_suffix(filename, ".webm")) datatype = Awesomium::WSLit("video/webm");
else if(has_suffix(filename, ".mp4"))  datatype = Awesomium::WSLit("video/mp4");
else if(has_suffix(filename, ".ogv"))  datatype = Awesomium::WSLit("video/ogg");
else if(has_suffix(filename, ".flv"))  datatype = Awesomium::WSLit("video/flv");

if(!datatype.IsEmpty())
{
FILE * pFile;
long lSize;
unsigned char * buffer;
size_t result;

pFile = fopen ( contentpath.c_str() , "rb" );
if (pFile!=NULL)
{
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);

// allocate memory to contain the whole file:
buffer = (unsigned char*) malloc (sizeof(unsigned char)*lSize);
if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}

// copy the file into the buffer:
result = fread (buffer,1,lSize,pFile);
if (result != lSize) {fputs ("Reading error",stderr); exit (3);}

//This is where the magic happens!!
return Awesomium::ResourceResponse::Create(lSize, buffer, datatype);

// terminate
fclose (pFile);
free (buffer);
}
else
{
//send this off to the default request handler instead of it being a local file
return Awesomium::ResourceInterceptor::OnRequest(request);
}
}else
{
//send this off to the default request handler instead of it being a local file
return Awesomium::ResourceInterceptor::OnRequest(request);
}
}

//Support function
bool ResInterceptor::has_suffix(const std::string &str, const std::string &suffix)
{
return str.size() >= suffix.size() &&
str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
}

Что касается того, как я подключил это, я просто добавил эту строку кода:

_web_core = WebCore::Initialize(config);
_web_core->set_resource_interceptor(new ResInterceptor());

Это заняло у меня целую ночь, чтобы придумать все, потому что я передавал указатель с переменной и не использовал ключевое слово «new» напрямую! Я понял это сейчас, по крайней мере!

Также обратите внимание, что я попробовал точно такой же код выше в LocalDataSource, и он не работал ни для чего, кроме текстовых файлов, так что я думаю, что там есть ошибка, хорошие новости, это работает точно так же, но вы получаете больше контроля над каждым запросом файла.

Спасибо Стивену за отличный код!

1

Другие решения

Самый простой способ — отправить содержимое файла без обнаружения потного пантомимы — использовать статический метод. static ResourceResponse* Awesomium::ResourceResponse::Create,

От Awesomium документы:

Создайте ResourceResponse из файла на диске.

Я не мог найти способ нанести на карту ResourceResponse::Create в DataSource::SendResponse,

В качестве обходного пути вы можете переписать свой источник данных как IResourceInterceptor вместо DataSource, Я написал подробный пример в C # на как использовать схему http: // вместо пользовательской схемы asset: // для встроенных ресурсов Это должно быть довольно просто, чтобы перевести C # на C ++. Ниже приведена отредактированная версия моего сообщения (не проверено).

using System;
using System.IO;
using System.Reflection;
using Awesomium.Core;

namespace MyApp
{
public class ResourceInterceptor : IResourceInterceptor
{
/// <summary>
///     Intercepts any requests for the EmbeddedResourceDomain base Uri,
///     and returns a response using the embedded resource in this app's assembly/DLL file
/// </summary>
public virtual ResourceResponse OnRequest(ResourceRequest request)
{
ResourceResponse response = null;
string resourceName;
string filePath;

filePath = String.Concat("./", request.Url.AbsolutePath);
filePath = Path.GetFullPath(resourceName.Replace('/', Path.DirectorySeparatorChar));

// cache the resource to a temp file if
if (File.Exists(filePath))
{
response = ResourceResponse.Create(filePath);
}

return response;
}

/// <summary>
///     Optionally blocks any web browser requests by returning true.  Not used.
/// </summary>
/// <remarks>
///     This method can implement a whitelist of allowed URLs here by
///     returning true to block any whitelist misses
/// </remarks>
public virtual bool OnFilterNavigation(NavigationRequest request)
{
return false;
}
}
}

Другим вариантом может быть взломать содержимое HTML, чтобы ввести <base href="file:///c:/my/bin/path" /> элемент внутри <head> документа. Вам необходимо изменить значение атрибута href перед загрузкой содержимого. Это может быть больше работы, чем оно того стоит.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector