cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: How to upload file as CouchDB attachment via libCurl

From: Dan Fandrich <dan_at_coneharvesters.com>
Date: Tue, 27 May 2014 08:40:46 +0200

On Mon, May 26, 2014 at 07:23:59PM -0500, Lane wrote:
> Let me clarify. What I consider an attachment, or what CouchDB considers an
> attachment is a file to the field. So _attachments is the json objects field,
> and the file would be the data to that field. As in my example, you’ll see the
> command line …
>
> curl -X POST 'http://localhost:5984/students' -H 'Content-Type: application/
> json' -d '{
>
>     "first":"John", "last":"Doe", "age":"20", "_attachments": {
>
>         "john.txt": {
>
>             "content-type": "text/plain",
>
>             "data": "'$(openssl base64 < /tmp/john_file.txt)'"
>
>         }
>
>     }
>
> }'
>
> I have no issues building the json stream. the code that says // build json
> stream here. That works, it was just a lot to write out.  

If it works, then what's the question?

> So that curl command works on the command line and does exactly what I want.
> What I don’t understand is how to upload the part within parenthesis, the
> actual file. I.e., $(openssl base64 < filename). This line converts the file to
> base64, then curl uploads it. That's the part I don't understand with the API
> or to build into the app to upload the file as part of the json object. And
> yes, its a huge file.

The data blob is just a big, ASCII string that needs to be POSTed. The string
gets built in the application and sent with libcurl, just as you've shown in
your example. Or is your question not about libcurl at all but about how to
generate that data blob? The easiest way is probably to just build a string
in place, reading from disk and using a base64 encoding routine to build what's
appended to the string. libcurl itself contains such a routine that could be
pulled into your application for this purpose (Curl_base64_encode).

But, if it's a large file, it's inefficient to build the string in its entirety
in RAM before sending it. In that case, it would be better to create a
CURLOPT_READFUNCTION that first sends the JSON data up to the "data": "' part,
then base64 encodes the file data a piece at a time and passes it into libcurl.
The example programs docs/examples/post-callback.c docs/examples/httpput.c and
docs/examples/ftpuploadresume.c show roughly how to use a callback, although
the (minor) complication will be to switch between the static JSON header and
footer portions and the encoded file data.

>>> Dan
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2014-05-27