C++ C++;卷曲post文件,然后获取响应错误

C++ C++;卷曲post文件,然后获取响应错误,c++,curl,C++,Curl,我试图将一个文件发布到API,然后检查各种响应。但是,每当我尝试发布大于0字节的文件时,都会出现错误: First-chance exception at 0x77AADF63 (ntdll.dll) in Test.exe: 0xC0000005: Access violation writing location 0x00000014. 有关守则如下: std::string Network::Post(std::string url, std::map<std::string,

我试图将一个文件发布到API,然后检查各种响应。但是,每当我尝试发布大于0字节的文件时,都会出现错误:

First-chance exception at 0x77AADF63 (ntdll.dll) in Test.exe: 
0xC0000005: Access violation writing location 0x00000014.
有关守则如下:

std::string Network::Post(std::string url, std::map<std::string, std::string> requestBody, std::string file, int port) {
    std::ostringstream response;

    std::stringstream bodyStream;
    struct stat file_info;


    for (std::map<std::string, std::string>::iterator iterator = requestBody.begin(); iterator != requestBody.end(); iterator++) {
        bodyStream << iterator->first << "=" << iterator->second << "&";
    }

    //Get file
    FILE* file_handle = fopen(file.c_str(), "rb");
    int t = fstat(_fileno(file_handle), &file_info);

    CURL *ch;
    curl_global_init(CURL_GLOBAL_ALL);
    ch = curl_easy_init();

    struct curl_slist *headers = NULL;

    curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");

    std::string bodyStreamString = bodyStream.str();
    const char* bodyStreamCharPtr = bodyStreamString.c_str();

    curl_easy_setopt(ch, CURLOPT_URL, url.c_str());
    curl_easy_setopt(ch, CURLOPT_PORT, port);
    curl_easy_setopt(ch, CURLOPT_POSTFIELDS, bodyStreamCharPtr);
    curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, bodyStream.str().length());
    curl_easy_setopt(ch, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(ch, CURLOPT_AUTOREFERER, 1);
    curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_easy_setopt(ch, CURLOPT_COOKIEFILE, "cookies.dat");
    curl_easy_setopt(ch, CURLOPT_COOKIEJAR, "cookies.dat");
    curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, &ResponseToString);
    curl_easy_setopt(ch, CURLOPT_VERBOSE, 1L);
    curl_easy_setopt(ch, CURLOPT_UPLOAD, 1L);
    curl_easy_setopt(ch, CURLOPT_READDATA, file_handle);
    curl_easy_setopt(ch, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
    curl_easy_setopt(ch, CURLOPT_WRITEDATA, &response);

    int res = curl_easy_perform(ch);
    curl_easy_cleanup(ch);

    return response.str();
}


size_t Network::ResponseToString(char *ptr, size_t size, size_t nmemb, void *stream) {
    std::ostringstream *s = (std::ostringstream*)stream;
    size_t count = size * nmemb;
    s->write(ptr, count);
    return count;
}
std::string Network::Post(std::string url,std::map requestBody,std::string文件,int端口){
std::ostringstream反应;
std::stringstream bodyStream;
结构统计文件信息;
for(std::map::iterator iterator=requestBody.begin();iterator!=requestBody.end();iterator++){

首先是bodyStream问题在于您的WRITEFUNC

我很确定Network::ResponseToString不是静态的,这会导致问题,因为非静态函数会将“this”作为第一个参数传递,然后拧动函数参数,我建议根本不要使用类成员,而是使用它(与Network::Post放在同一个文件中,并在Post方法定义之前):

还要记住改变:

curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, &ResponseToString);
在:

此外,如果您的作用域是一个简单的“post”,则不需要在curl opt声明中指定的许多头:


我决定通过Fiddler将我的应用程序中的所有请求传递给Fiddler,但我发现没有任何请求被发送,返回时出现了一个错误(n中发送了0个字节)。因此,我仔细研究了一下,发现了这个问题

aa问题是我缺少READFUNCTION。解决方法如下:

curl_easy_setopt(ch, CURLOPT_READDATA, file_handle);
curl_easy_setopt(ch, CURLOPT_READFUNCTION, &RequestToFile);
这就是读取功能。显然,它是windows所必需的

size_t EasyCloud::Network::RequestToFile(void *ptr, size_t size, size_t nmemb, FILE *stream) {

    curl_off_t nread;

    size_t retcode = fread(ptr, size, nmemb, stream);

    nread = (curl_off_t)retcode;

    return retcode;
}

使用调试器时,您观察到了什么?完全没有。它只是在“int res=curl\u easy\u perform(ch)”处中断,无法单步执行。如果我删除WRITEFUNCTION和WRITEDATA选项,它会工作,但无法获得响应。问题似乎也不在ResponseToString方法中。不,不是这样。它是静态的(在标头中定义)。该错误似乎发生在我调用curl\u easy\u perform之后,但在调用WRITEFUNCTION之前。请尝试删除我在回答中列出的4个选项,可能它们的存在触发了一些奇怪的curl行为。您的回答解决了我的问题!谢谢@gabry
curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, bodyStream.str().length());
curl_easy_setopt(ch, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(ch, CURLOPT_READDATA, file_handle);
curl_easy_setopt(ch, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
curl_easy_setopt(ch, CURLOPT_READDATA, file_handle);
curl_easy_setopt(ch, CURLOPT_READFUNCTION, &RequestToFile);
size_t EasyCloud::Network::RequestToFile(void *ptr, size_t size, size_t nmemb, FILE *stream) {

    curl_off_t nread;

    size_t retcode = fread(ptr, size, nmemb, stream);

    nread = (curl_off_t)retcode;

    return retcode;
}