windows C++-windows C++-使用任务和 XML HTTP 请求进行连接(三)

10. 添加下载和响应的代码:

//使用指定的方法开始下载指定的URI。返回的任务生成
//HTTP响应文本。可以使用GetStatusCode()和GetReasonPrase()读取状态代码和原因。
task<wstring> HttpRequest::DownloadAsync(PCWSTR httpMethod, PCWSTR uri, cancellation_token cancellationToken,
    PCWSTR contentType, IStream* postStream, uint64 postStreamSizeToSend)
{
    // Create an IXMLHTTPRequest2 object.
    ComPtr<IXMLHTTPRequest2> xhr;
    CheckHResult(CoCreateInstance(CLSID_XmlHttpRequest, nullptr, CLSCTX_INPROC, IID_PPV_ARGS(&xhr)));

    // Create callback.
    auto stringCallback = Make<HttpRequestStringCallback>(xhr.Get(), cancellationToken);
    CheckHResult(stringCallback ? S_OK : E_OUTOFMEMORY);

    auto completionTask = create_task(stringCallback->GetCompletionEvent());

    // Create a request.
    CheckHResult(xhr->Open(httpMethod, uri, stringCallback.Get(), nullptr, nullptr, nullptr, nullptr));

    if (postStream != nullptr && contentType != nullptr)
    {
        CheckHResult(xhr->SetRequestHeader(L"Content-Type", contentType));
    }

    // Send the request.
    CheckHResult(xhr->Send(postStream, postStreamSizeToSend));

    // Return a task that completes when the HTTP operation completes. 
    // We pass the callback to the continuation because the lifetime of the 
    // callback must exceed the operation to ensure that cancellation 
    // works correctly.
    return completionTask.then([this, stringCallback](tuple<HRESULT, wstring> resultTuple)
    {
        // If the GET operation failed, throw an Exception.
        CheckHResult(std::get<0>(resultTuple));

        statusCode = stringCallback->GetStatusCode();
        reasonPhrase = stringCallback->GetReasonPhrase();

        return std::get<1>(resultTuple);
    });
}

11. 添加在指定的URI上启动HTTP GET代码:

//在指定的URI上启动HTTP GET。返回的任务在整个响应完成后完成
//并且该任务生成HTTP响应文本。状态代码和原因
//可以使用GetStatusCode()和GetReasonPrase()读取。
task<wstring> HttpRequest::GetAsync(Uri^ uri, cancellation_token cancellationToken)
{
    return DownloadAsync(L"GET",
                         uri->AbsoluteUri->Data(),
                         cancellationToken,
                         nullptr,
                         nullptr,
                         0);
}

void HttpRequest::CreateMemoryStream(IStream **stream)
{
    auto randomAccessStream = ref new Windows::Storage::Streams::InMemoryRandomAccessStream();
    CheckHResult(CreateStreamOverRandomAccessStream(randomAccessStream, IID_PPV_ARGS(stream)));
}

12. 添加启动POST的代码:

//使用字符串体在指定的URI上启动HTTP POST。返回的任务生成
//HTTP响应文本。可以使用GetStatusCode()和GetReasonPrase()读取状态代码和原因。
task<wstring> HttpRequest::PostAsync(Uri^ uri, const wstring& body, cancellation_token cancellationToken)
{
    int length = 0;
    ComPtr<IStream> postStream;
    CreateMemoryStream(&postStream);

    if (body.length() > 0)
    {
        // Get the required buffer size.
        int size = WideCharToMultiByte(CP_UTF8,                         // UTF-8
                                       0,                               // Conversion type
                                       body.c_str(),                    // Unicode string to convert
                                       static_cast<int>(body.length()), // Size
                                       nullptr,                         // Output buffer
                                       0,                               // Output buffer size
                                       nullptr,
                                       nullptr);
        CheckHResult((size != 0) ? S_OK : HRESULT_FROM_WIN32(GetLastError()));

        std::unique_ptr<char[]> tempData(new char[size]);
        length = WideCharToMultiByte(CP_UTF8,                         // UTF-8
                                     0,                               // Conversion type
                                     body.c_str(),                    // Unicode string to convert
                                     static_cast<int>(body.length()), // Size
                                     tempData.get(),                  // Output buffer
                                     size,                            // Output buffer size
                                     nullptr,
                                     nullptr);
        CheckHResult((length != 0) ? S_OK : HRESULT_FROM_WIN32(GetLastError()));
        CheckHResult(postStream->Write(tempData.get(), length, nullptr));
    }

    return DownloadAsync(L"POST",
                         uri->AbsoluteUri->Data(),
                         cancellationToken,
                         L"text/plain;charset=utf-8",
                         postStream.Get(),
                         length);
}

13. 添加流媒体启动POST的函数:

//使用流媒体在指定的URI上启动HTTP POST。返回的任务生成
//HTTP响应文本。可以使用GetStatusCode()和GetReasonPrase()读取状态代码和原因。
task<wstring> HttpRequest::PostAsync(Uri^ uri, PCWSTR contentType, IStream* postStream,
    uint64 postStreamSizeToSend, cancellation_token cancellationToken)
{
    return DownloadAsync(L"POST",
                         uri->AbsoluteUri->Data(),
                         cancellationToken,
                         contentType,
                         postStream,
                         postStreamSizeToSend);
}

14.  添加发送请求的函数代码:

//发送请求,但不返回响应。相反,让调用者使用ReadAsync()读取它。
task<void> HttpRequest::SendAsync(const wstring& httpMethod, Uri^ uri, cancellation_token cancellationToken)
{
    // Create an IXMLHTTPRequest2 object.
    ComPtr<IXMLHTTPRequest2> xhr;
    CheckHResult(CoCreateInstance(CLSID_XmlHttpRequest, nullptr, CLSCTX_INPROC, IID_PPV_ARGS(&xhr)));

    // Create callback.
    buffersCallback = Make<Web::Details::HttpRequestBuffersCallback>(xhr.Get(), cancellationToken);
    CheckHResult(buffersCallback ? S_OK : E_OUTOFMEMORY);

    ComPtr<IXMLHTTPRequest2Callback> xhrCallback;
    CheckHResult(buffersCallback.As(&xhrCallback));

    // Open and send the request.
    CheckHResult(xhr->Open(httpMethod.c_str(),
                           uri->AbsoluteUri->Data(),
                           xhrCallback.Get(),
                           nullptr,
                           nullptr,
                           nullptr,
                           nullptr));

    responseComplete = false;

    CheckHResult(xhr->Send(nullptr, 0));

    // Return a task that completes when the HTTP operation completes.
    // Since buffersCallback holds a reference on the callback, the lifetime of the callback will exceed
    // the operation and ensure that cancellation works correctly.
    return buffersCallback->CreateDataTask().then([this]()
    {
        CheckHResult(buffersCallback->GetError());

        statusCode = buffersCallback->GetStatusCode();
        reasonPhrase = buffersCallback->GetReasonPhrase();
    });
}

15. 添加同步读的代码:

//从HTTP响应中读取一块数据,直到指定长度或到达末尾
//并将该值存储在提供的缓冲区中。这对于大内容是有用的,
//从而能够流式传输结果。
task<void> HttpRequest::ReadAsync(Windows::Storage::Streams::IBuffer^ readBuffer, unsigned int offsetInBuffer,
    unsigned int requestedBytesToRead)
{
    if (offsetInBuffer + requestedBytesToRead > readBuffer->Capacity)
    {
        throw ref new InvalidArgumentException();
    }

    // Return a task that completes when a read completes. 
    // We pass the callback to the continuation because the lifetime of the 
    // callback must exceed the operation to ensure that cancellation 
    // works correctly.
    return buffersCallback->CreateDataTask().then([this, readBuffer, offsetInBuffer, requestedBytesToRead]()
    {
        CheckHResult(buffersCallback->GetError());

        // Get a pointer to the location to copy data into.
        ComPtr<IBufferByteAccess> bufferByteAccess;
        CheckHResult(reinterpret_cast<IUnknown*>(readBuffer)->QueryInterface(IID_PPV_ARGS(&bufferByteAccess)));
        byte* outputBuffer; // Returned internal pointer, do not free this value.
        CheckHResult(bufferByteAccess->Buffer(&outputBuffer));

        // Copy bytes from the sequential stream into the buffer provided until
        // we reach the end of one or the other.
        readBuffer->Length = buffersCallback->ReadData(outputBuffer + offsetInBuffer, requestedBytesToRead);
        if (buffersCallback->IsResponseReceived() && (readBuffer->Length < requestedBytesToRead))
        {
            responseComplete = true;
        }
    });
}

注意: 在 HttpRequest.cpp 中添加的代码包括7~15。 

在网页开发中,HTTP(Hypertext Transfer Protocol)和XML(eXtensible Markup Language)经常结合使用。 首先,HTTP是一种用于在网络上传输数据的协议,它负责浏览器和服务器之间的通信。而XML是一种用于描述数据的标记语言,它可以将数据以可读性很高的格式进行编码。 在使用HTTPXML结合时,通常的情况是,客户端浏览器通过发送HTTP请求到服务器来获取数据。服务器会将数据以XML格式进行编码,并通过HTTP响应返回给客户端。客户端浏览器再通过解析XML数据来提取所需的信息,并将其展示给用户。 一个常见的例子是使用Ajax技术来实现异步通信。通过Ajax,客户端浏览器可以在不重新加载整个页面的情况下与服务器进行通信。在这种情况下,客户端浏览器会通过发送HTTP请求来获取数据,服务器会将数据以XML格式编码,然后通过HTTP响应返回给客户端。客户端浏览器再通过JavaScript代码解析XML数据,并将数据动态展示在页面上。 另外,HTTPXML也可以结合在Web服务中使用。Web服务是一种通过网络进行通信和交互的软件系统。在使用Web服务时,客户端浏览器通过发送HTTP请求来调用服务器上的特定功能。服务器会将响应以XML格式返回给客户端,客户端再通过解析XML数据来获取服务器提供的信息和功能。 总之,HTTPXML可以结合使用,通过HTTP传输XML数据,实现数据的传递和交互。这种结合为网页开发提供了更加灵活和可扩展的方式,使得数据传输和展示更加方便和高效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值