zoukankan      html  css  js  c++  java
  • 编写你的应用程序(九)、网址加载

    原文链接:https://developer.chrome.com/native-client/devguide/coding/url-loading 

    注意:已针对ChromeOS以外的平台公布了此处所述技术的弃用。
    请访问我们的 迁移指南 了解详情。


    网址加载

    介绍

    本节介绍如何使用URLLoader API将服务器中的图像和声音文件等资源加载到应用程序中。

    本节中讨论的示例包含在目录中的SDK中 examples/api/url_loader

    参考信息

    有关从URL加载数据的参考信息,请参阅以下文档:

    背景

    当用户启动Native Client Web应用程序时,Chrome会下载并缓存应用程序的HTML文件,清单文件(.nmf)和Native Client模块(.pexe或.nexe)。如果您的应用程序需要其他资源(如图像和声音文件),则必须明确加载这些资产。您可以使用本节中介绍的Pepper API将URL中的资源加载到应用程序中。

    将资产加载到应用程序后,Chrome将缓存这些资产。但是,为了避免出现Chrome缓存的奇思妙想,您可能希望使用Pepper FileIO API将这些资源写入用户文件系统上的持久沙盒位置。

    这个url_loader例子

    SDK包含一个示例,用于url_loader演示从服务器下载文件。此示例包含以下主要文件:

    • index.html - 启动Native Client模块的HTML代码。
    • example.js - index.html的JavaScript文件。它具有在单击“获取URL”按钮时向Native Client模块发送PostMessage请求的代码。
    • url_loader_success.html- 服务器上的HTML文件,其内容使用URLLoaderAPI 检索。
    • url_loader.cc - 设置和提供和进入Native客户端模块的入口点的代码。
    • url_loader_handler.cc - 检索url_loader_success.html文件内容并返回结果的代码(这是完成大部分工作的地方)。

    本文档的其余部分介绍了url_loader.cc和 url_loader_handler.cc文件中的代码。

    网址加载概述

    与许多Pepper API一样,URLLoaderAPI包含一组异步执行的方法,并在Native Client模块中调用回调函数。该url_loader示例的高级流程如下所述。请注意,命名空间pp::URLLoader中的方法是Pepper URLLoaderAPI的一部分 ,而其余​​的函数是Native Client模块中的代码的一部分(特别是在文件中url_loader_handler.cc)。下图显示了url_loader_handler代码的流程:

    /native-client/images/pepper-urlloader-api.png

    以下是URL加载中涉及的高级步骤。

    1. Native Client模块调用pp::URLLoader::Open以开始打开URL。
    2. Open完成时,它调用本机客户端模块中的回调函数(在这种情况下,OnOpen)。
    3. Native Client模块调用Pepper函数 URLLoader::ReadResponseBody以开始读取包含数据的响应主体。ReadResponseBody在Native Client模块中传递一个可选的回调函数(在本例中为On Read)。回调函数是一个可选的回调函数,因为ReadResponseBody如果数据可用,它可以读取数据并同步返回(这可以提高大文件和快速连接的性能)。

    本文档的其余部分演示了如何在url_loader示例中实现前面的步骤。

    url_loader 深入解读

    设置请求

    HandleMessagein url_loader.cc创建一个URLLoaderHandler实例并将其传递给要检索的资产的URL。然后HandleMessage 调用Start开始从服务器检索资产:

    void URLLoaderInstance::HandleMessage(const pp::Var& var_message) {
      if (!var_message.is_string()) {
        return;
      }
      std::string message = var_message.AsString();
      if (message.find(kLoadUrlMethodId) == 0) {
        // The argument to getUrl is everything after the first ':'.
        size_t sep_pos = message.find_first_of(kMessageArgumentSeparator);
        if (sep_pos != std::string::npos) {
          std::string url = message.substr(sep_pos + 1);
          printf("URLLoaderInstance::HandleMessage('%s', '%s')
    ",
                 message.c_str(),
                 url.c_str());
          fflush(stdout);
          URLLoaderHandler* handler = URLLoaderHandler::Create(this, url);
          if (handler != NULL) {
            // Starts asynchronous download. When download is finished or when an
            // error occurs, |handler| posts the results back to the browser
            // vis PostMessage and self-destroys.
            handler->Start();
          }
        }
      }
    }

    请注意,URLLoaderHandlerin 的构造函数url_loader_handler.cc设置了URL请求的参数(使用 SetURL,SetMethod和,SetRecordDownloadProgress):

    URLLoaderHandler::URLLoaderHandler(pp::Instance* instance,
                                       const std::string& url)
        : instance_(instance),
          url_(url),
          url_request_(instance),
          url_loader_(instance),
          buffer_(new char[READ_BUFFER_SIZE]),
          cc_factory_(this) {
      url_request_.SetURL(url);
      url_request_.SetMethod("GET");
      url_request_.SetRecordDownloadProgress(true);
    }

    下载数据

    Startin 使用a url_loader_handler.cc创建一个callback(cc) CompletionCallbackFactory。传递回调以Open在完成时调用。Open开始加载URLRequestInfo

    void URLLoaderHandler::Start() {
      pp::CompletionCallback cc =
          cc_factory_.NewCallback(&URLLoaderHandler::OnOpen);
      url_loader_.Open(url_request_, cc);
    }

    OnOpen确保Open调用成功,如果是,则调用 GetDownloadProgress以确定要下载的数据量,以便为响应正文分配内存。

    请注意,要下载的数据量可能是未知的,在这种情况下 GetDownloadProgress设置total_bytes_to_be_received为-1。如果total_bytes_to_be_received设置为-1或GetDownloadProgress失败则不是问题; 在这些情况下,读缓冲区的存储器不能提前分配,必须在接收数据时分配。

    最后,OnOpen回调ReadBody.

    void URLLoaderHandler::OnOpen(int32_t result) {
      if (result != PP_OK) {
        ReportResultAndDie(url_, "pp::URLLoader::Open() failed", false);
        return;
      }
      int64_t bytes_received = 0;
      int64_t total_bytes_to_be_received = 0;
      if (url_loader_.GetDownloadProgress(&bytes_received,
                                          &total_bytes_to_be_received)) {
        if (total_bytes_to_be_received > 0) {
          url_response_body_.reserve(total_bytes_to_be_received);
        }
      }
      url_request_.SetRecordDownloadProgress(false);
      ReadBody();
    }

    ReadBody创建另一个CompletionCallback(a NewOptionalCallback)并将其传递给ReadResponseBody,读取响应主体, AppendDataBytes,并将结果数据附加到先前读取的数据。

    void URLLoaderHandler::ReadBody() {
      pp::CompletionCallback cc =
          cc_factory_.NewOptionalCallback(&URLLoaderHandler::OnRead);
      int32_t result = PP_OK;
      do {
        result = url_loader_.ReadResponseBody(buffer_, READ_BUFFER_SIZE, cc);
        if (result > 0) {
          AppendDataBytes(buffer_, result);
        }
      } while (result > 0);
    
      if (result != PP_OK_COMPLETIONPENDING) {
        cc.Run(result);
      }
    }
    
    void URLLoaderHandler::AppendDataBytes(const char* buffer, int32_t num_bytes) {
      if (num_bytes <= 0)
        return;
      num_bytes = std::min(READ_BUFFER_SIZE, num_bytes);
      url_response_body_.insert(
          url_response_body_.end(), buffer, buffer + num_bytes);
    }

    最终要么已经为整个文件读取了所有字节(结果为PP_OK或0),所有字节都已经被读取了已经下载的内容,但更多的是要下载(PP_OK_COMPLETIONPENDING或-1),或者有错误(少于比-1)。OnRead如果发生错误或被调用PP_OK

    显示结果

    ReportResultAndDie当出现错误或PP_OK返回时,OnRead调用以指示文件流已完成。ReportResultAndDie然后调用ReportResult,哪些调用PostMessage将结果发送回HTML页面。

    CC-By 3.0许可下提供的内容

  • 相关阅读:
    [杂谈]关于前端如何学习框架的一点牢骚
    【2018】面试复习大纲
    迟来的2017总结
    [转载并收藏]JavaScript 疲劳终极指南:我们行业的真相
    想做好产品,一定要成为自己产品的用户
    2017年个人提升计划
    Chrome新发现
    不要被所在的公司或企业绑架
    半夜不想睡有感
    2016年总结
  • 原文地址:https://www.cnblogs.com/SunkingYang/p/11049125.html
Copyright © 2011-2022 走看看