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-80, // Conversion typebody.c_str(), // Unicode string to convertstatic_cast<int>(body.length()), // Sizenullptr, // Output buffer0, // Output buffer sizenullptr,nullptr);CheckHResult((size != 0) ? S_OK : HRESULT_FROM_WIN32(GetLastError()));std::unique_ptr<char[]> tempData(new char[size]);length = WideCharToMultiByte(CP_UTF8, // UTF-80, // Conversion typebody.c_str(), // Unicode string to convertstatic_cast<int>(body.length()), // SizetempData.get(), // Output buffersize, // Output buffer sizenullptr,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。