Я использую libcurl для загрузки файла прошивки на аппаратное устройство.Я использую multipart / form-data, и похоже, что загрузка файла начинается нормально, но не загружает весь файл.
Загружаемый файл имеет размер 144 855 725 байт, но, похоже, только два блока по 64 КБпослал.
В размещенном коде я использую функцию обратного вызова чтения.Я также пытался просто передать имя файла в функцию curl_mime_filedata, и результаты были одинаковыми.
Одно интересное замечание: при запуске программы я получаю успешный ответ от curl_easy_perform примерно половину времени.В другую половину времени я получу ошибку 56 «Сбой при получении данных от однорангового узла».Еще одно интересное замечание: существует небольшое расхождение в размере файла (144 855 725) и размере, который локон воспринимает как размер загрузки (144 856 042).Я предполагаю, что это потому, что он учитывает все байты в теле (не только файл).Это правильно?
Вот некоторые (урезанные) выходные данные, когда я запускаю программу.
Размер файла: 144855725
ОБЩЕЕ ВРЕМЯ: 0,000092
ВВЕРХ: 0 из 0 ВНИЗ: 00
UP: 0 из 144856042 DOWN: 0 из 0
ReadCallback: Size = 1, Nmemb = 65267
Мы читаем 65267 байтов из файла
UP: 65536 из 144856042 DOWN: 0 из 0
ReadCallback: Size = 1, Nmemb = 65536
Мы читаем 65536 байтов из файла
UP: 131072 из 144856042 DOWN: 0 из 0
результат curl ERROR = <56: Ошибка при получении данных изpeer>
Не удалось загрузить файл прошивки
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;
}
int main(void)
{
CURL *pCurl;
CURLcode res;
std::stringstream ss;
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);
// Add the Content-Disposition
part = curl_mime_addpart(multipart);
curl_mime_name(part, "Content-Disposition");
curl_mime_data(part, "form-data; name=\"upgrade_file\"; filename=\"\"", CURL_ZERO_TERMINATED);
// Add the file
part = curl_mime_addpart(multipart);
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, NULL, NULL, pFile);
curl_easy_setopt(pCurl, CURLOPT_MIMEPOST, multipart);
// This is a long upload, disable the timeout
curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 0L);
// Create headers
ss.str("");
ss << "Authorization: Bearer " << accessToken;
headerList = curl_slist_append(headerList, ss.str().c_str());
// Accept
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);
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);
}
Я ожидаю, что будет загружен весь файл, а не пара фрагментов файла.