0

I'm using c++ and Casablanca to add Dropbox functionality to our software.

I can log in using OAuth 2, get metadata, open files, and save files using files_put successfully. I can't however figure out how to save a file using /files (POST).

I'm using code similar to this: (i.e. I have removed some functions to just show the hardcoded strings I end up with)

{
    using concurrency::streams::file_stream;
    using concurrency::streams::basic_istream;

    utility::string_t strURI = L"https://api-content.dropbox.com/1/files/dropbox/";
    uri url(uri::encode_uri(strURI));

    utility::string_t sb = url.to_string();
    sb += L"?oauth_consumer_key=" + consumerKey + L"&";
    sb += L"oauth_nonce=" + nonce + L"&";       
    sb += L"oauth_timestamp=" + timestamp + L"&";   
    sb += L"oauth_version=2.0";
    sb += L"&access_token=" + accessToken;
    sb += L"&file=" + strFilename; // I've tried with and without this line

    return file_stream<unsigned char>::open_istream(strPath)
        .then([sb, url, &bRet](task<basic_istream<unsigned char>> previousTask)
    {
        try
        {
            auto fileStream = previousTask.get();
            //get the content length, used to set the Content-Length property
            fileStream.seek(0, std::ios::end);
            auto length = static_cast<size_t>(fileStream.tell());
            fileStream.seek(0, 0);

            // Make HTTP request with the file stream as the body.                      
            http_request req;
            http_client client(sb);
            req.set_body(fileStream);
            req.set_method(methods::POST);
            return client.request(req)
                .then([fileStream, &bRet](task<http_response> previousTask)
            {
                // Process response
            }
        }
    };
}

I get a bad request response. I assume the problem is that I'm not giving it the filename parameter correctly, but I don't know where it's supposed to go. Or maybe I'm missing something else entirely.

Can anyone please help clarify this for me?

kpg207
  • 1
  • 1
  • Why would you want to use `/files (POST)`? As the documentation says, `files_put` is preferred. – user94559 Apr 04 '14 at 19:44
  • I am also adding functionality to connect to another cloud with a similar api, and it does not have files_put available. – kpg207 Apr 07 '14 at 14:16

1 Answers1

0

One side-note, I think you're using OAuth 2, but you're constructing a signature sort of like an OAuth 1 signature. I believe you can just do this:

utility::string_t sb = url.to_string();
sb += L"?access_token=" + accessToken;

Though it's slightly preferable to put the access token in the auth header: Authorization: Bearer <access token>.

I'm not 100% sure, but I believe /files (POST) requires a multipart-form-encoded body (and so the file name comes from the attachment in the body). I'm not sure how to accomplish that with Casablanca. But I would really stick to /files_put for Dropbox and use POST requests only for the platforms that require it (and perhaps they have simpler interfaces for that call).

user94559
  • 59,196
  • 6
  • 103
  • 103