linux C/++ libcurl form-data 表单post 二进制数据流到后台服务器
/*
添加form-data 表单项 以提交文件片段为例
文件分片form字段
*/
int WebUploader::curlPostSlice(SliceFile& file,int sliceIndex,string &zoneMd5)
{
struct curl_httppost *formpost = NULL;
struct curl_httppost *lastptr = NULL;
CURLFORMcode resultForm;
int ret =0;
struct curl_httppost *p = NULL;
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "id",
CURLFORM_COPYCONTENTS, (const char *) "WU_FILE_0", CURLFORM_END );
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "name",
CURLFORM_COPYCONTENTS, (const char *) file.file_name().c_str(), CURLFORM_END );
//application/octet-stream
//video/mp4
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "type",
CURLFORM_COPYCONTENTS, (const char *) file.content_type().c_str(), CURLFORM_END );
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "lastModifiedDate",
CURLFORM_COPYCONTENTS, (const char *) file.lastModifiedDate().c_str(), CURLFORM_END );
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "size",
CURLFORM_COPYCONTENTS, (const char *) to_string(file.file_size()).c_str(), CURLFORM_END );
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "chunk",
CURLFORM_COPYCONTENTS, (const char *) to_string(sliceIndex).c_str(), CURLFORM_END );
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "fileMd5",
CURLFORM_COPYCONTENTS, (const char *) file.file_md5().c_str(), CURLFORM_END );
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "contentType",
CURLFORM_COPYCONTENTS, (const char *) file.content_type().c_str(), CURLFORM_END );
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "zoneTotalMd5",
CURLFORM_COPYCONTENTS, (const char *) file.file_md5().c_str(), CURLFORM_END );
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "zoneMd5",
CURLFORM_COPYCONTENTS, (const char *) zoneMd5.c_str(), CURLFORM_END );
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "zoneTotalCount",
CURLFORM_COPYCONTENTS, (const char *) to_string(file.slice_num()).c_str(), CURLFORM_END );
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "zoneNowIndex",
CURLFORM_COPYCONTENTS, (const char *) to_string(sliceIndex).c_str(), CURLFORM_END );
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "zoneTotalSize",
CURLFORM_COPYCONTENTS, (const char *) to_string(file.file_size()).c_str(), CURLFORM_END );
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "zoneStartSize",
CURLFORM_COPYCONTENTS, (const char *) to_string(file.slice_size()*sliceIndex).c_str(), CURLFORM_END );
//Content-Disposition: form-data; name="zoneEndSize"
//
//386726
int zoneEndSize = file.slice_size()*(sliceIndex+1) > file.file_size()? file.file_size(): file.slice_size()*(sliceIndex+1);
resultForm = curl_formadd( &formpost, &lastptr, CURLFORM_COPYNAME, "zoneEndSize",
CURLFORM_COPYCONTENTS, (const char *) to_string(zoneEndSize).c_str(), CURLFORM_END );
//Content-Disposition: form-data;name="file";filename="yolov5s_zhc_foodSmokePhone_13330_300_960_2022-05-12.rknn"
//Content-Type: application/octet-stream
//填冲二进制流上传:
resultForm = curl_formadd(&formpost,&lastptr,
CURLFORM_COPYNAME, "file",
CURLFORM_BUFFER, file.file_name().c_str(),
CURLFORM_BUFFERPTR, file.get_slice_data(sliceIndex),
CURLFORM_BUFFERLENGTH, file.get_slice_data_size(sliceIndex),
CURLFORM_CONTENTTYPE, "application/octet-stream",
CURLFORM_END);
//curl_formadd
if(resultForm!=CURL_FORMADD_OK){
printf("curl_formadd faild:%d\n",resultForm);
return -1;
}
p = formpost;
do{
printf("%s,%s,%d\n",p->name, p->contents,p->contentslength);
p = p->next;
}while(p!=lastptr);
clear_ws_reault(&_ws_result);
ret = curlPostFormDataWithBin(file,sliceIndex,_upload_url.c_str(),formpost,&_ws_result);
if(ret == 0 && strstr(_ws_result.json_data,"\"success\":true,\"code\":10000,")){
//upload sucess
ret = 0;
}else{
printf("curlPostFormDataWithBin fiald ret:%d,%d\n",ret,_ws_result.curl_res);
}
return ret;
}
/*
* 提交form 表单数据
* 提交文件二进制片段
* return
* 0 sucess
*
*/
int WebUploader::curlPostFormDataWithBin(SliceFile& file,int sliceIndex,const char* _url, struct curl_httppost* formpost,CURL_CALL_RESULT* result)
{
CURLcode res;
struct curl_slist * _http_headers;
char *progress_data = (char*)NULL;
BOOL prevent_cache = TRUE;
_http_headers = curl_slist_append(_http_headers, "Content-Type: multipart/form-data;");
curl_easy_setopt(_curlHandle, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(_curlHandle, CURLOPT_SSL_VERIFYPEER, 0L);//忽略证书检查
curl_easy_setopt(_curlHandle, CURLOPT_URL, _url);
curl_easy_setopt(_curlHandle, CURLOPT_POST, 1L);
curl_easy_setopt(_curlHandle, CURLOPT_HTTPHEADER, _http_headers); //设置发送http头部
curl_easy_setopt(_curlHandle, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(_curlHandle, CURLOPT_TIMEOUT, 10L); //设置超时时间
//重要!!!多线程下禁用控制域名解析的alarm 超时
curl_easy_setopt(_curlHandle, CURLOPT_NOSIGNAL, prevent_cache);
curl_easy_setopt(_curlHandle, CURLOPT_PROGRESSDATA, &file);
curl_easy_setopt(_curlHandle, CURLOPT_NOPROGRESS, FALSE);
curl_easy_setopt(_curlHandle, CURLOPT_PROGRESSFUNCTION,WebUploader::web_service_progress_func);
curl_easy_setopt(_curlHandle, CURLOPT_WRITEDATA, result);
curl_easy_setopt(_curlHandle, CURLOPT_WRITEFUNCTION,WebUploader::web_service_rsp_write_func);
curl_easy_setopt(_curlHandle, CURLOPT_VERBOSE, 1L);
printf("enter curl ws call: curl=%p, ws_result_ptr=%p....\n",
_curlHandle,
result);
//printf( "curl_easy_perform()....\n");
res = curl_easy_perform(_curlHandle);
result->curl_res = res;
return (int)res;
}