C++ 为什么文件上传会在发送了几个数据块(使用多部分/表单数据)后停止?

C++ 为什么文件上传会在发送了几个数据块(使用多部分/表单数据)后停止?,c++,windows,multipartform-data,libcurl,C++,Windows,Multipartform Data,Libcurl,我正在使用libcurl将固件文件上载到硬件设备。我使用的是多部分/表单数据,看起来文件上传启动正常,但不会加载整个文件。 我上传的文件是144855725字节,但似乎只发送了两个64k块 在发布的代码中,我使用了一个read回调函数。我还尝试将文件名传递给curl\u mime\u filedata函数,结果是一样的。 一个有趣的注意事项是,当我运行这个程序时,我会从curl\u easy\u执行程序中得到成功的响应,大约有一半的时间。另一半时间,我会收到错误56“从对等方接收数据时失败”。

我正在使用libcurl将固件文件上载到硬件设备。我使用的是多部分/表单数据,看起来文件上传启动正常,但不会加载整个文件。
我上传的文件是144855725字节,但似乎只发送了两个64k块

在发布的代码中,我使用了一个read回调函数。我还尝试将文件名传递给curl\u mime\u filedata函数,结果是一样的。
一个有趣的注意事项是,当我运行这个程序时,我会从curl\u easy\u执行程序中得到成功的响应,大约有一半的时间。另一半时间,我会收到错误56“从对等方接收数据时失败”。 另一个有趣的注意事项是,文件的大小(144855725)与curl认为的下载大小(144856042)略有差异。我认为这是因为它占用了正文中的所有字节(不仅仅是文件)。对吗

以下是我运行程序时的一些(精简)输出。
文件大小:144855725
总时间:0.000092
向上:0/0向下:0/0
上升:144856042的0下降:0的0
ReadCallback:Size=1,Nmemb=65267
我们从文件中读取了65267个字节
上升:144856042的65536下降:0的0
ReadCallback:Size=1,Nmemb=65536
我们从文件中读取了65536个字节
上升:131072/144856042下降:0/0
卷曲结果错误=
无法上载固件文件

size_t ReadCallback(char *BufferOut, size_t Size, size_t Nmemb, void *StreamIn)
{
   curl_off_t nread;
   size_t retcode = fread(BufferOut, Size, Nmemb, (FILE *)StreamIn);
   nread = (curl_off_t)retcode;
   cout << "ReadCallback: Size=" << Size << ", Nmemb=" << Nmemb << endl;
   cout << "We read " << nread << " bytes from the file" << endl;
   return retcode;
}
size\t ReadCallback(char*BufferOut、size\t size、size\t Nmemb、void*StreamIn)
{
卷曲,卷曲,卷曲;
size\u t retcode=fread(BufferOut,size,Nmemb,(FILE*)StreamIn);
nread=(curl_off_t)retcode;

cout您没有正确填充
curl\u mime
结构。您显示的代码与您在以下文档中描述的mime格式不匹配:

--1a2fc07a-d882-4470-a1da-79716d34cd9b 内容处置:表单数据;name=“升级文件”filename=“” 内容类型:应用程序/八位字节流 //文件数据在这里// --1a2fc07a-d882-4470-a1da-79716d34cd9b 内容处置:表单数据;name=“提交” 安装操作系统 --1a2fc07a-d882-4470-a1da-79716d34cd9b-- 请尝试以下方法:

size_t ReadCallback(char *buffer, size_t size, size_t nitems, void *arg)
{
    cout << "ReadCallback: size=" << size << ", nitems=" << nitems << endl;
    size_t retcode = fread(buffer, size, nitems, (FILE *)arg);
    cout << "We read " << retcode << " bytes from the file" << endl;
    return retcode;
}

int SeekCallback(void *arg, curl_off_t offset, int origin)
{
    if (fseek((FILE *)arg, offset, origin) == 0)
        return CURL_SEEKFUNC_OK;
    else
        return CURL_SEEKFUNC_FAIL;
}

int main()
{
    CURL *pCurl;
    CURLcode res;
    struct curl_slist *headerList = NULL;
    string accessToken;
    struct TransferProgress transProgress;
    string filePath;
    FILE * pFile;
    long lSize;

    curl_global_init(CURL_GLOBAL_ALL);
    pCurl = curl_easy_init();
    if (pCurl)
    {
        EC520UutComms comms;
        curl_mime *multipart;
        curl_mimepart *part;

        accessToken = comms.GetAccessToken(pCurl);
        SetOptionsToDefault(pCurl);

        // Specify the target URL
        std::string str(comms.BaseURL() + kAPI_Upgrade);
        cout << "URL <" + str + ">" << endl;
        curl_easy_setopt(pCurl, CURLOPT_URL, str.c_str());

        multipart = curl_mime_init(pCurl);

        part = curl_mime_addpart(multipart);
        curl_mime_name(part, "upgrade_file");
        curl_mime_filename(part, "");
        curl_mime_type(part, "application/octet-stream");
        filePath = "C:\\Temp\\TestFile.tst";
        // curl_mime_filedata(part, filePath.c_str());
        fopen_s(&pFile, filePath.c_str(), "rb");
        // obtain file size:
        fseek(pFile, 0, SEEK_END);
        lSize = ftell(pFile);
        rewind(pFile);
        cout << "File size: " << lSize << endl;
        curl_mime_data_cb(part, lSize, ReadCallback, SeekCallback, NULL, pFile);

        part = curl_mime_addpart(multipart);
        curl_mime_name(part, "submit");
        curl_mime_data(part, "Install OS", CURL_ZERO_TERMINATED);

        curl_easy_setopt(pCurl, CURLOPT_MIMEPOST, multipart);

        // This is a long upload, disable the timeout
        curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 0L);

        // Create headers
        headerList = curl_slist_append(headerList, ("Authorization: Bearer " + accessToken).c_str());
        headerList = curl_slist_append(headerList, "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");

        curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, headerList);

        curl_easy_setopt(pCurl, CURLOPT_XFERINFOFUNCTION, TransferInfo);

        transProgress.curl = pCurl;
        curl_easy_setopt(pCurl, CURLOPT_XFERINFODATA, &transProgress);

        curl_easy_setopt(pCurl, CURLOPT_NOPROGRESS, 0L);

        // Now send the message
        res = curl_easy_perform(pCurl);

        fclose(pFile);
        curl_slist_free_all(headerList);
        curl_mime_free(multipart);

        if (res == CURLE_OK)
        {
            cout << "Firmware file successfully uploaded" << endl;
        }
        else
        {
            cout << "curl result ERROR = <" + to_string(res) + ": " + curl_easy_strerror(res) + ">" << endl;
            cout << "Failed to upload firmware file" << endl;
        }

        curl_easy_cleanup(pCurl);
    }

    return 0;
}
size\t ReadCallback(字符*缓冲区、大小、大小元素、void*arg)
{

cout您没有正确填充
curl\u mime
结构。您显示的代码与您在以下文档中描述的mime格式不匹配:

--1a2fc07a-d882-4470-a1da-79716d34cd9b 内容处置:表单数据;name=“升级文件”filename=“” 内容类型:应用程序/八位字节流 //文件数据在这里// --1a2fc07a-d882-4470-a1da-79716d34cd9b 内容处置:表单数据;name=“提交” 安装操作系统 --1a2fc07a-d882-4470-a1da-79716d34cd9b-- 请尝试以下方法:

size_t ReadCallback(char *buffer, size_t size, size_t nitems, void *arg)
{
    cout << "ReadCallback: size=" << size << ", nitems=" << nitems << endl;
    size_t retcode = fread(buffer, size, nitems, (FILE *)arg);
    cout << "We read " << retcode << " bytes from the file" << endl;
    return retcode;
}

int SeekCallback(void *arg, curl_off_t offset, int origin)
{
    if (fseek((FILE *)arg, offset, origin) == 0)
        return CURL_SEEKFUNC_OK;
    else
        return CURL_SEEKFUNC_FAIL;
}

int main()
{
    CURL *pCurl;
    CURLcode res;
    struct curl_slist *headerList = NULL;
    string accessToken;
    struct TransferProgress transProgress;
    string filePath;
    FILE * pFile;
    long lSize;

    curl_global_init(CURL_GLOBAL_ALL);
    pCurl = curl_easy_init();
    if (pCurl)
    {
        EC520UutComms comms;
        curl_mime *multipart;
        curl_mimepart *part;

        accessToken = comms.GetAccessToken(pCurl);
        SetOptionsToDefault(pCurl);

        // Specify the target URL
        std::string str(comms.BaseURL() + kAPI_Upgrade);
        cout << "URL <" + str + ">" << endl;
        curl_easy_setopt(pCurl, CURLOPT_URL, str.c_str());

        multipart = curl_mime_init(pCurl);

        part = curl_mime_addpart(multipart);
        curl_mime_name(part, "upgrade_file");
        curl_mime_filename(part, "");
        curl_mime_type(part, "application/octet-stream");
        filePath = "C:\\Temp\\TestFile.tst";
        // curl_mime_filedata(part, filePath.c_str());
        fopen_s(&pFile, filePath.c_str(), "rb");
        // obtain file size:
        fseek(pFile, 0, SEEK_END);
        lSize = ftell(pFile);
        rewind(pFile);
        cout << "File size: " << lSize << endl;
        curl_mime_data_cb(part, lSize, ReadCallback, SeekCallback, NULL, pFile);

        part = curl_mime_addpart(multipart);
        curl_mime_name(part, "submit");
        curl_mime_data(part, "Install OS", CURL_ZERO_TERMINATED);

        curl_easy_setopt(pCurl, CURLOPT_MIMEPOST, multipart);

        // This is a long upload, disable the timeout
        curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 0L);

        // Create headers
        headerList = curl_slist_append(headerList, ("Authorization: Bearer " + accessToken).c_str());
        headerList = curl_slist_append(headerList, "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");

        curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, headerList);

        curl_easy_setopt(pCurl, CURLOPT_XFERINFOFUNCTION, TransferInfo);

        transProgress.curl = pCurl;
        curl_easy_setopt(pCurl, CURLOPT_XFERINFODATA, &transProgress);

        curl_easy_setopt(pCurl, CURLOPT_NOPROGRESS, 0L);

        // Now send the message
        res = curl_easy_perform(pCurl);

        fclose(pFile);
        curl_slist_free_all(headerList);
        curl_mime_free(multipart);

        if (res == CURLE_OK)
        {
            cout << "Firmware file successfully uploaded" << endl;
        }
        else
        {
            cout << "curl result ERROR = <" + to_string(res) + ": " + curl_easy_strerror(res) + ">" << endl;
            cout << "Failed to upload firmware file" << endl;
        }

        curl_easy_cleanup(pCurl);
    }

    return 0;
}
size\t ReadCallback(字符*缓冲区、大小、大小元素、void*arg)
{

你的建议修改成功了。我感谢你的时间。非常感谢!你的建议修改成功了。我感谢你的时间。非常感谢!
size_t ReadCallback(char *buffer, size_t size, size_t nitems, void *arg)
{
    cout << "ReadCallback: size=" << size << ", nitems=" << nitems << endl;
    size_t retcode = fread(buffer, size, nitems, (FILE *)arg);
    cout << "We read " << retcode << " bytes from the file" << endl;
    return retcode;
}

int SeekCallback(void *arg, curl_off_t offset, int origin)
{
    if (fseek((FILE *)arg, offset, origin) == 0)
        return CURL_SEEKFUNC_OK;
    else
        return CURL_SEEKFUNC_FAIL;
}

int main()
{
    CURL *pCurl;
    CURLcode res;
    struct curl_slist *headerList = NULL;
    string accessToken;
    struct TransferProgress transProgress;
    string filePath;
    FILE * pFile;
    long lSize;

    curl_global_init(CURL_GLOBAL_ALL);
    pCurl = curl_easy_init();
    if (pCurl)
    {
        EC520UutComms comms;
        curl_mime *multipart;
        curl_mimepart *part;

        accessToken = comms.GetAccessToken(pCurl);
        SetOptionsToDefault(pCurl);

        // Specify the target URL
        std::string str(comms.BaseURL() + kAPI_Upgrade);
        cout << "URL <" + str + ">" << endl;
        curl_easy_setopt(pCurl, CURLOPT_URL, str.c_str());

        multipart = curl_mime_init(pCurl);

        part = curl_mime_addpart(multipart);
        curl_mime_name(part, "upgrade_file");
        curl_mime_filename(part, "");
        curl_mime_type(part, "application/octet-stream");
        filePath = "C:\\Temp\\TestFile.tst";
        // curl_mime_filedata(part, filePath.c_str());
        fopen_s(&pFile, filePath.c_str(), "rb");
        // obtain file size:
        fseek(pFile, 0, SEEK_END);
        lSize = ftell(pFile);
        rewind(pFile);
        cout << "File size: " << lSize << endl;
        curl_mime_data_cb(part, lSize, ReadCallback, SeekCallback, NULL, pFile);

        part = curl_mime_addpart(multipart);
        curl_mime_name(part, "submit");
        curl_mime_data(part, "Install OS", CURL_ZERO_TERMINATED);

        curl_easy_setopt(pCurl, CURLOPT_MIMEPOST, multipart);

        // This is a long upload, disable the timeout
        curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 0L);

        // Create headers
        headerList = curl_slist_append(headerList, ("Authorization: Bearer " + accessToken).c_str());
        headerList = curl_slist_append(headerList, "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");

        curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, headerList);

        curl_easy_setopt(pCurl, CURLOPT_XFERINFOFUNCTION, TransferInfo);

        transProgress.curl = pCurl;
        curl_easy_setopt(pCurl, CURLOPT_XFERINFODATA, &transProgress);

        curl_easy_setopt(pCurl, CURLOPT_NOPROGRESS, 0L);

        // Now send the message
        res = curl_easy_perform(pCurl);

        fclose(pFile);
        curl_slist_free_all(headerList);
        curl_mime_free(multipart);

        if (res == CURLE_OK)
        {
            cout << "Firmware file successfully uploaded" << endl;
        }
        else
        {
            cout << "curl result ERROR = <" + to_string(res) + ": " + curl_easy_strerror(res) + ">" << endl;
            cout << "Failed to upload firmware file" << endl;
        }

        curl_easy_cleanup(pCurl);
    }

    return 0;
}