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

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

Кто-нибудь знает, куда я должен идти отсюда?

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.


person ChillyFlashER    schedule 24.01.2014    source источник


Ответы (2)


Я знаю, что это старо, но это имело отношение ко мне, я исправил это так же, как Стивен, я опубликую код 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());

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

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

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

person Krum110487    schedule 25.07.2014
comment
Также имейте в виду, что этот код пронизан ошибками :). - person thesaint; 01.11.2014
comment
В основном это был тестовый код, чтобы заставить его работать :) Но суть понятна. - person Krum110487; 10.11.2014
comment
если вы не говорили о awesomium, с чем я согласен, я провел большую часть своего времени, пытаясь решить проблемы. - person Krum110487; 10.11.2014
comment
да, awesomium на самом деле отстой в этом отношении. Просто слишком много ошибок. но также совершенно очевидно, что ваш код является тестовым кодом, по крайней мере, для меня. но слишком много людей склонны просто копировать пасту: D. - person thesaint; 10.11.2014

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

Из 2/cpp_api/class_awesomiumstatic ResourceResponse* Awesomium::ResourceResponse::Create1_resource_response.html#ab8d6f5fdfb8bd1436aa64d21d9eaab90" rel="nofollow">документов Awesomium:

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

Я не мог найти способ сопоставить ResourceResponse::Create с DataSource::SendResponse.

В качестве обходного пути вы можете переписать источник данных как IResourceInterceptor вместо DataSource. Я написал подробный пример на C# для http://answers.awesomium.com/questions/3597/can-you-rewrite-urls-in-resourceinterceptoronreque.html Перевод 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 перед загрузкой содержимого. Это может быть больше работы, чем оно того стоит.

person Steve Jansen    schedule 02.02.2014