简体   繁体   中英

How to define metadata with libcurl?

I do following command with curl (the command line tool) to upload a file to google drive:

curl --request POST \
    'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart' \
    --header 'Authorization: Bearer "..."' \
    -F "metadata={name : 'backup.zip'};type=application/json;charset=UTF-8" \
    -F "@backup.zip;type=application/zip"

The following programm with libcurl could only use the URL , the header and upload the file using formdata:

#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
    CURL *curl;
    CURLcode res;

    curl_global_init(CURL_GLOBAL_DEFAULT);

    curl = curl_easy_init();
    if(curl) {


        struct curl_slist *chunk= NULL;
        chunk= curl_slist_append(chunk, "Authorization: Bearer \"...\"");
        curl_slist_append(chunk, "Accept: application/json");
        curl_slist_append(chunk, "Content-Type: application/json");

        curl_mimepart *part= NULL;
        curl_mime_type(part, "application/octet-stream");


        struct curl_httppost* formpost = NULL;
        struct curl_httppost* lastptr = NULL;
        curl_formadd(&formpost,
                     &lastptr,
                     CURLFORM_COPYNAME, "sendfile",
                     CURLFORM_FILE, "main.c",
                     CURLFORM_END);


        /* Perform the request, res will get the return code */
        //curl_easy_setopt(curl, CURLOPT_URL, "https://www.googleapis.com/drive/v3/files");
        curl_easy_setopt(curl, CURLOPT_URL, "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
        curl_easy_setopt(curl, CURLOPT_MIMEPOST, part);
        curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

        curl_easy_perform(curl);

        /* always cleanup */
        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();


    return 0;
}

How can I specify the -F "metadata={name : 'backup.zip'};type=application/json;charset=UTF-8" in libcurl ?

I tried it with CURLFORM_COPYNAME but this doesn't work.

You are setting the HTTP request's top-level Content-Type header to application/json , which is wrong. It needs to be multipart/related instead, per Google's documentation: Send a multipart upload request .

The command-line you showed is inserting a MIME part of type application/json into the POST form data, but you are not doing the same thing in your code.

Also, you should not be using CURLOPT_MIMEPOST and CURLOPT_HTTPPOST together. Use ONE or the OTHER, not BOTH. CURLOPT_HTTPPOST is deprecated, replaced by CURLOPT_MIMEPOST . And you are not even passing the correct input value to CURLOPT_MIMEPOST anyway. It expects a curl_mime* , not a curl_mimepart* .

Try something more like this instead:

#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
    CURL *curl;
    CURLcode res;

    curl_global_init(CURL_GLOBAL_DEFAULT);

    curl = curl_easy_init();
    if (curl)
    {
        /* set custom HTTP headers */

        struct curl_slist *header = NULL;

        // uncomment this if you are not using libcurl 7.61.0 or later...
        //
        // header = curl_slist_append(header, "Authorization: Bearer \"...\"");
        //

        header = curl_slist_append(header, "Content-Type: multipart/related");
        header = curl_slist_append(header, "Accept: application/json");

        /* set MIME post content */

        curl_mime *mime = curl_mime_init(curl);

        curl_mimepart *part = curl_mime_addpart(mime);
        curl_mime_name(part, "metadata");
        curl_mime_type(part, "application/json;charset=UTF-8");
        curl_mime_data(part, "{\"name\" : \"backup.zip\"}", CURL_ZERO_TERMINATED);

        part = curl_mime_addpart(mime);
        curl_mime_type(part, "application/zip");
        curl_mime_filedata(part, "backup.zip");

        /* Perform the request, res will get the return code */

        curl_easy_setopt(curl, CURLOPT_URL, "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart");
        curl_easy_setopt(curl, CURLOPT_POST, 1); 
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
        curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);

        // comment this out if you are not using libcurl 7.61.0 or later...
        //
        curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BEARER);
        curl_easy_setopt(curl, CURLOPT_XOAUTH2_BEARER, "...");
        //

        res = curl_easy_perform(curl);

        /* always cleanup */
        curl_slist_free_all(header);
        curl_mime_free(mime);
        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();

    return 0;
}

Or maybe this (I'm not sure the correct way to specify the HTTP Content-Type when using a MIME body - documentation and examples are very limited on this topic, most of the examples I found are for SMTP, not HTTP):

#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
    CURL *curl;
    CURLcode res;

    curl_global_init(CURL_GLOBAL_DEFAULT);

    curl = curl_easy_init();
    if (curl)
    {
        /* set custom HTTP headers */

        struct curl_slist *header = NULL;

        // uncomment this if you are not using libcurl 7.61.0 or later...
        //
        // header = curl_slist_append(header, "Authorization: Bearer \"...\"");
        //

        header = curl_slist_append(header, "Accept: application/json");

        /* set MIME post content */

        curl_mime *mime = curl_mime_init(curl);

        curl_mime *rel = curl_mime_init(curl);

        curl_mimepart *part = curl_mime_addpart(rel);
        curl_mime_name(part, "metadata");
        curl_mime_type(part, "application/json;charset=UTF-8");
        curl_mime_data(part, "{\"name\" : \"backup.zip\"}", CURL_ZERO_TERMINATED);

        part = curl_mime_addpart(rel);
        curl_mime_type(part, "application/zip");
        curl_mime_filedata(part, "backup.zip");

        part = curl_mime_addpart(mime);
        curl_mime_type(part, "multipart/related"); 
        curl_mime_subparts(part, rel); 

        /* Perform the request, res will get the return code */

        curl_easy_setopt(curl, CURLOPT_URL, "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart");
        curl_easy_setopt(curl, CURLOPT_POST, 1); 
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
        curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);

        // comment this out if you are not using libcurl 7.61.0 or later...
        //
        curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BEARER);
        curl_easy_setopt(curl, CURLOPT_XOAUTH2_BEARER, "...");
        //

        res = curl_easy_perform(curl);

        /* always cleanup */
        curl_slist_free_all(header);
        curl_mime_free(mime);
        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM