C++ 如何使用libcurl定义元数据?

C++ 如何使用libcurl定义元数据?,c++,http,C++,Http,我使用curl(命令行工具)执行以下命令将文件上载到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;char

我使用
curl
(命令行工具)执行以下命令将文件上载到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"
以下带有
libcurl
的程序只能使用
URL
标题
并使用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;
}
#包括
#包括
内部主(空)
{
卷曲*卷曲;
卷曲编码;
curl\u global\u init(curl\u global\u默认值);
curl=curl_easy_init();
if(curl){
struct curl_slist*chunk=NULL;
chunk=curl\u slist\u append(chunk,“Authorization:Bearer\”…\”);
curl_slist_append(chunk,“Accept:application/json”);
curl_slist_append(chunk,“内容类型:application/json”);
curl_mimepart*part=NULL;
curl_mime_类型(部分,“应用程序/八位字节流”);
结构curl_httppost*formpost=NULL;
struct curl_httppost*lastptr=NULL;
卷曲模板和模板柱,
&lastptr,
CURLFORM_COPYNAME,“sendfile”,
CURLFORM_文件,“main.c”,
卷曲(U端);
/*执行请求,res将获得返回代码*/
//curl\u easy\u setopt(curl,CURLOPT\u URL,“https://www.googleapis.com/drive/v3/files");
curl\u easy\u setopt(curl,CURLOPT\u URL,“https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart");
curl\u easy\u setopt(curl,CURLOPT\u HTTPHEADER,chunk);
卷曲(卷曲、卷曲、部件);
curl_easy_setopt(curl,CURLOPT_HTTPPOST,formpost);
旋度,易于执行(旋度);
/*总是清理*/
旋度\轻松\清洁(旋度);
}
curl_global_cleanup();
返回0;
}
如何在
libcurl
中指定
-F“metadata={name:'backup.zip'};type=application/json;charset=UTF-8”


我用
CURLFORM\u COPYNAME
尝试了它,但这不起作用。

您将HTTP请求的顶级
内容类型
头设置为
application/json
,这是错误的。根据谷歌的文档,它需要是多部分/相关的

您显示的命令行正在将类型为
application/json
的MIME部分插入POST表单数据中,但您在代码中没有做同样的事情

此外,您不应该同时使用
CURLOPT_MIMEPOST
CURLOPT_HTTPPOST
。使用其中一个,而不是两个
CURLOPT_HTTPPOST
已被弃用,替换为
CURLOPT_MIMEPOST
。而且您甚至没有将正确的输入值传递给
CURLOPT_MIMEPOST
。它需要一个
curl\u mime*
,而不是
curl\u mimepart*

请尝试类似以下内容:

#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;
}

您是否阅读了添加表单数据的libcurl文档?是的。我添加了一个表单数据。要上载的文件。但是我不知道如何在libcul中定义元数据。这个例子不起作用。标题仍然是
未命名的
@JohnSmith您需要更具体一些。到底是什么不起作用?你指的是什么标题?你原来的问题中没有提到任何标题。在最坏的情况下,您可以(也可能应该)查看
curl.exe的源代码,看看它是如何将命令行参数转换为特定的libcurl函数调用的;这不管用。文件名总是
无标题的
。我试图从curl源代码中学习,但不要理解它。@JohnSmith我自己目前无权测试libcurl,但如果您捕获正在发送的原始HTTP请求数据(请参阅和),然后编辑您的问题以显示该数据,我可以告诉你它的格式是否符合谷歌的预期。我已经尝试过这种方法和几乎所有的curl\u mime\ux函数,但从未得到发送任何数据的表单。。。只是一直挂着。。。在详细的请求头中没有边界或任何表单数据
#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;
}