How to download Image file.

Jun 17, 2013 at 12:39 PM
Hello.

I need to receive image using the GET method. (like WinInet::InternetReadFile)
Then I will load image using stream(WIC Bitmap), and download file to my local disk.

But I do not know what to use any Stream or Buffer.
Jun 17, 2013 at 8:04 PM
You can use our HTTP and streams library to do this.
Please refer to the BingRequest sample, installed under %programfiles(x86)%\Microsoft Cpp REST SDK for VS 2012\SDK\samples\ (when you install the C++ REST SDK).

The steps would be:
  1. Open a file buffer in output mode (this will create a file on the disk)
  2. Send a GET request using the http_client, receive the http_response.
  3. Read the response body into the file buffer. This will download the file to the disk.
Here is the code snippet that will take care of this, I am using a local URL (http://localhost:60009/img.jpg), replace this with the URL from which you want to download the file.
    // Open a stream to the file to write the HTTP response body into.
    auto fileBuffer = std::make_shared<streambuf<uint8_t>>();
    return file_buffer<uint8_t>::open(L"img.jpg", std::ios::out ).then([=](streambuf<uint8_t> outFile) -> pplx::task<http_response>
    {
        *fileBuffer = outFile; 

        // Create an HTTP request.
        http_client client(U("http://localhost:60009/img.jpg"));
        return client.request(methods::GET);
    })
        // Write the response body into the file buffer.
        .then([=](http_response response) -> pplx::task<size_t>
    {
        printf("Response status code %u returned.\n", response.status_code());
        return response.body().read_to_end(*fileBuffer);
    })
        // Close the file buffer.
        .then([=](size_t datasize)
    {
        std::cout << datasize;
        return fileBuffer->close();
    }).wait();
Let us know if this solves your issue.
Jun 18, 2013 at 2:35 AM
Edited Jun 18, 2013 at 2:36 AM
Hi kavyako.

I solved to download image thanks to you.
and I have a few more questions.
  1. I've tried to use "streambuf<uint8_t> *fileBuffer" instead of "auto fileBuffer = std::make_shared<streambuf<uint8_t>>()", Of course, an error has occurred. Why should I use "make_shared" ?
  2. I want to copy body to unsigned char of array for image load using memory ( response.body() copy to unsigned char[context-length] ). Is it possible?
Jun 20, 2013 at 10:19 PM
Answers inline:
  1. Using smart pointers, you do not have to deal with the object lifetimes. Using a pointer to a streambuf should also work, just ensure that you are taking care of allocating and deallocating the memory.
  2. There are a couple of options to read the data from the response into memory:
    a. If you know the content length of the body, use the rawptr_buffer. It is a memory based buffer that supports reading sequences of characters to or from a fixed size block.
    uint8_t data[128];
    rawptr_buffer<uint8_t> tbuf(data, 128);
    response.body().read_to_end(tbuf).get();
b. Another option is to use the container_buffer. This is a memory based buffer that supports reading/writing to a collection (std::vector/std::string).
Use the .collection() method on the container_buffer to access the underlying collection. For instance,
    auto cbuffer = std::make_shared<container_buffer<std::vector<uint8_t>>>();
    response.body().read_to_end(*cbuffer).get();
    auto data = cbuffer->collection();
c. Also take a look at our producerconsumerstream.

You can refer to the input stream tests for examples on how to use the different types of stream buffers. Here is a link to those tests: https://casablanca.codeplex.com/SourceControl/latest#Release/tests/Functional/streams/istream_tests.cpp

Let me know if you have any other queries.
Jul 5, 2013 at 2:55 AM
Edited Jul 5, 2013 at 6:29 AM
hi kavyako.

I implement using b type.
pplx::task<std::vector<uint8_t>>RequestFileStreamAsync(http_request& requestMsg)
{
    http_client client(requestMsg.request_uri());
    
    return client.request(requestMsg.method()).then([&](http_response response) 
        {
                 if(response.status_code() == status_codes::OK)
                {
            return response.extract_vector();
                 }
        else
        {
            pplx::cancel_current_task();
        }
        });
}

use method


RequestFileStreamAsync(request).then([&](pplx::task<std::vector<uint8_t>> byteBuffer)
{
           std::vector<uint8_t> buffer = byteBuffer.get();
         
           do other things....
}
Let me know whether I did well :)

And i have one more question.
I want to show download progress status.
Can i do this using REST SDK?