Sending a file via multipart using libcurl in C++ - c++

I am trying to upload a file via a POST request to a remote location using libcurl and C++. However, I think I am doing something wrong because I am told that the file doesn't arrive on the other side.
I am using the following code:
#include "curl/curl.h"
using namespace std;
size_t WriteCallback(void * buffer, size_t size, size_t count, void * user)
{
((string *) user)->append((char *) buffer, 0, size * count);
return size * count;
}
int main()
{
curl_global_init(CURL_GLOBAL_ALL);
CURL * Curl;
CURLCode res;
Curl = curl_easy_init();
curl_easy_setopt(Curl, CURLOPT_FAILONERROR, 0);
curl_easy_setopt(Curl, CURLOPT_VERBOSE, 1L);
struct curl_httppost * formpost = NULL;
struct curl_httppost * lastptr = NULL;
struct curl_slist * headerlist = NULL;
static const char buf[] = "Expect:";
ImageName = "myimage.jpg"
ImageNameWithPath = "/this/location/right/here/" + ImageName;
curl_formadd(& formpost,
& lastptr,
CURLFORM_COPYNAME, ImageName.c_str();
CURLFORM_FILE, ImageNameWithPath.c_str();
CURLFORM_CONTENTTYPE, "image/jpeg (binary)";
CURLFORM_END);
curl_formadd(& formpost,
& lastptr,
CURLFORM_COPYNAME, ImageName.c_str();
CURLFORM_COPYCONTENTS, ImageNameWithPath.c_str();
CURLFORM_CONTENTTYPE, "image/jpeg (binary)";
CURLFORM_END);
headerlist = curl_slist_append(headerlist, buf);
string MessageBodyLine1 = "Content-Disposition: form-data; name=\"file\"; filename\"" + ImageName + "\"";
headerlist = curl_slist_append(headerlist, MessageBodyLine1.c_str());
string Url = https://www.example.com/ // There is a real URL here
curl_easy_setopt(Curl, CURLOPT_URL, Ulr.c_str());
curl_easy_setopt(Curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(Curl, CURLOPT_HTTPPOST, formpost);
string Reponse;
curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(Curl, CURLOPT_WRITEDATA, & Response);
res = curl_easy_perform(Curl);
curl_easy_cleanup(Curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
curl_global_cleanup();
return 0;
I actually expected the output to look something like this somewhere
POST URL HTTP/1.1
Content-Type: multipart/form-data; boundary=----BoundaryString
----BoundaryString
Content-Disposition: form-data; name="file"; filename="myfile.jpg"
Content-Type: image/jpeg (binary)
and instead I get this:
* Trying IP
* Connected to IP port PORT (#0)
POST URL HTTP/1.1
Host: IP
Accept: IP:PORT
Content-Disposition: form-data; name="file"; filename="myfile.jpg"
Content-Length: totalsize
Content-Type: multipart/form-data; boundary=----BoundaryString
< HTTP/1.1 200 OK
[...]
Now it says OK but I know for a fact that the image does not arrive on the other side. Furthermore my Response string is also empty whereas it should contain a JSON string.
What am I doing wrong? Unfortunately I am stuck with a older libcurl version and thus cannot use the mime format available in curl 7.55.

DO NOT add a Content-Disposition request header to the headerlist of the HTTP request, it does not belong there. It belongs inside each MIME part instead (ie, you should be using CURLFORM_COPYNAME, "file" and CURLFORM_FILE, ImageName.c_str()). I would expect curl_formadd() to handle the Content-Disposition for you, you should not need to create it manually.
Also, image/jpeg (binary) is not a valid Content-Type value, it needs to be just image/jpeg.
And why are you calling curl_formadd() twice for the same file, one with CURLFORM_FILE and the other with CURLFORM_COPYCONTENTS? Especially since your input to CURLFORM_COPYCONTENTS is wrong (it expects a pointer to actual data, not a pointer to a filename string). You should be using only CURLFORM_FILE in this situation.
Try this:
#include "curl/curl.h"
#include <string>
using namespace std;
size_t WriteCallback(void * buffer, size_t size, size_t count, void * user)
{
size_t numBytes = size * count;
static_cast<string*>(user)->append(static_cast<char*>(buffer), 0, numBytes);
return numBytes;
}
int main()
{
curl_global_init(CURL_GLOBAL_ALL);
CURL *Curl = curl_easy_init();
if (!Curl)
return -1;
curl_easy_setopt(Curl, CURLOPT_FAILONERROR, 0);
curl_easy_setopt(Curl, CURLOPT_VERBOSE, 1L);
curl_httppost *formpost = NULL;
curl_httppost *lastptr = NULL;
string ImageName = "myimage.jpg";
string ImageNameWithPath = "/this/location/right/here/" + ImageName;
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "file",
CURLFORM_FILE, ImageNameWithPath.c_str(),
CURLFORM_CONTENTTYPE, "image/jpeg",
CURLFORM_END);
curl_slist *headerlist = curl_slist_append(NULL, "Expect:");
string Url = https://www.example.com/ // There is a real URL here
curl_easy_setopt(Curl, CURLOPT_URL, Url.c_str());
curl_easy_setopt(Curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(Curl, CURLOPT_HTTPPOST, formpost);
string Reponse;
curl_easy_setopt(Curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(Curl, CURLOPT_WRITEDATA, &Response);
CURLCode res = curl_easy_perform(Curl);
curl_easy_cleanup(Curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
curl_global_cleanup();
return 0;
}

Related

How to send soap(xml) request using libcurl

I am trying to send a SOAP request in xml format to a SOAP service using libcurl but i am getting error like" 500 internal server error" while posting the request in soap service.
I have tried almost all the approaches available online.
#include <stdio.h>
#include <curl/curl.h>
int main()
{
FILE * wfp = fopen("res.xml", "w+"); //File pointer to write the soap response
if (!wfp) {
perror("Write File Open:");
// exit(0);
}
struct curl_slist *header = NULL;
header = curl_slist_append(header, "Content-type: text/xml; charset=utf-8");
header = curl_slist_append(header, "SOAPAction: http://localhost:62634/Service1.svc");
header = curl_slist_append(header, "Transfer-Encoding: chunked");
header = curl_slist_append(header, "Expect:");
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost:62634/Service1.svc");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "<?xml version=\"1.0\" encoding=\"UTF-8\"?><soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:AddNumbers=\"http://localhost:62634/Service1.svc\"><soapenv:Header/><soapenv:Body><AddNumbers xmlns=\"http://tempuri.org/\"><number1>4</number1><number2>5</number2></AddNumbers></soapenv:Body></soapenv:Envelope>");
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); //Gets data to be written to file
curl_easy_setopt(curl, CURLOPT_WRITEDATA, wfp); //Writes result to file
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)-1);
//curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 1;
}
}

How to define metadata with libcurl?

I do following command with curl (the command line tool) to upload a file to 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"
The following programm with libcurl could only use the URL, the header and upload the file using 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;
}
How can I specify the -F "metadata={name : 'backup.zip'};type=application/json;charset=UTF-8" in libcurl?
I tried it with CURLFORM_COPYNAME but this doesn't work.
You are setting the HTTP request's top-level Content-Type header to application/json, which is wrong. It needs to be multipart/related instead, per Google's documentation: Send a multipart upload request.
The command-line you showed is inserting a MIME part of type application/json into the POST form data, but you are not doing the same thing in your code.
Also, you should not be using CURLOPT_MIMEPOST and CURLOPT_HTTPPOST together. Use ONE or the OTHER, not BOTH. CURLOPT_HTTPPOST is deprecated, replaced by CURLOPT_MIMEPOST. And you are not even passing the correct input value to CURLOPT_MIMEPOST anyway. It expects a curl_mime*, not a curl_mimepart*.
Try something more like this instead:
#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;
}
Or maybe this (I'm not sure the correct way to specify the HTTP Content-Type when using a MIME body - documentation and examples are very limited on this topic, most of the examples I found are for SMTP, not HTTP):
#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;
}

HTTP POST with Basic Auth and Fields (libcurl c++)

I am trying to make an HTTP POST using libcurl. The HTTP POST needs to perform a Basic Authentication, include a field and send a file in multi part. What I am using at the moment is the following:
FILE* fo = nullptr;
std::string fullErrPath(errPath);
fullErrPath.append("debug.txt");
fo = fopen(fullErrPath.c_str(), "wb");
CURL *curl;
CURLcode res;
struct curl_httppost* formpost = nullptr;
struct curl_httppost* lastptr = nullptr;
struct curl_slist* headerlist = nullptr;
static const char buf[] = "Expect:";
const char* imgPath = "/path/to/image.jpg";
curl_global_init(CURL_GLOBAL_ALL);
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "jpgdata",
CURLFORM_FILE, imgPath,
CURLFORM_CONTENTTYPE, "image/jpeg",
CURLFORM_END);
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "submit",
CURLFORM_COPYCONTENTS, "send"
CURLFORM_END);
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, urlupload);
headerlist = curl_slist_append(headerlist, buf);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
//curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "field=1");
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC);
curl_easy_setopt(curl, CURLOPT_USERPWD, credentials);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_STDERR, fo);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
// Response information
int httpCode(0);
static std::string httpData;
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &httpData);
res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
fclose(fo);
}
I left on purpose this part "//curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "field=1");" commented because I found online that it does not make sense to use it with CURLOPT_HTTPPOST. This is the post. But code above does not work.
First, the http response code I get from the server is 400 and by checking "debug.txt", in fact, there is no data. I see only the header.
Second, I need to include the POST field "field=1", but I do not know how to do it without using the command "curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "field=1");".
Thanks.
First, you want to set CURLOPT_USERPWD for the Basic auth.
Then, you need to decide which format of the data you want to POST. Do you want it to be multipart formpost or "regular" - you cannot mix them as that's just how HTTP works. The curl_formadd() you're doing so far is multipart formpost, and CURLOPT_POSTFIELDS is the regular one ("application/x-www-form-urlencoded").
So you say you want to add a "field=1" to the post, and to do that and keep this a multipart formpost you can insert the following snippet after your second call to curl_formadd. It adds another "part" to the post with the name and contents you asked for:
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "field",
CURLFORM_COPYCONTENTS, "1"
CURLFORM_END);

Curl post null object

I used example code from curl's help, but server receives empty objects and null custom header. GET method works fine. strbuf.GetString() - it's json object which converted to String.
CURL *curl;
CURLcode res;
struct WriteThis pooh;
res = curl_global_init(CURL_GLOBAL_DEFAULT);
struct curl_slist *headers=NULL;
curl_slist_append(headers, "Accept: application/json");
curl_slist_append( headers, "Content-Type: application/json");
curl_slist_append( headers, "charset: utf-8");
curl_slist_append( headers, "AuthToken: 9BA1B05482567E64037573FFB68672DCB52E4993");
curl = curl_easy_init();
if (curl)
{
pooh.readptr = strbuf.GetString();
pooh.sizeleft = (long)strlen(strbuf.GetString());
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
curl_easy_setopt(curl, CURLOPT_READDATA, &pooh);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,writer);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, &pooh);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, pooh.sizeleft);
res = curl_easy_perform(curl);
if (CURLE_OK == res)
{
char *ct;
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
if((CURLE_OK == res) && ct){
}
}
curl_easy_cleanup(curl);
}
curl_global_cleanup();
struct WriteThis {
const char *readptr;
long sizeleft;
};
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
struct WriteThis *pooh = (struct WriteThis *)userp;
if(size*nmemb < 1)
return 0;
if(pooh->sizeleft) {
*(char *)ptr = pooh->readptr[0]; /* copy one single byte */
pooh->readptr++; /* advance pointer */
pooh->sizeleft--; /* less data left */
return 1; /* we return 1 byte at a time! */
}
return 0; /* no more data left to deliver */
}
You set both a read callback and CURLOPT_POSTFIELDS. That's not useful. You need to decide which way you want to provide the data. In this case, I believe it will use the POSTFIELDS and just ignore the read callback.
The pointer you pass to CURLOPT_POSTFIELDS is not a string so libcurl will send funny binary "garbage" from there. You probably want to pass in pooh.readptr there.
Instead:
struct curl_slist *headers = NULL;
curl_slist_append(headers, "Accept: application/json");
curl_slist_append(headers, "Content-Type: application/json");
curl_slist_append(headers, "charset: utf-8");
curl_slist_append(headers, "AuthToken: 9BA1B05482567E64037573FFB68672DCB52E4993");
curl = curl_easy_init();
This:
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Accept: application/json");
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, "charset: utf-8");
headers = curl_slist_append(headers, "AuthToken: 9BA1B05482567E64037573FFB68672DCB52E4993");
curl = curl_easy_init();

uploading image to Parse server using libcurl in c++

I have the below code which performs the upload operation! its returning me, url and name but that url is invalid/there is no image, what i'm doing wrong?
CURL *curl;
CURLcode res;
struct curl_httppost *formpost=NULL;
struct curl_httppost *lastptr=NULL;
struct curl_slist *headerlist=NULL;
static const char buf[] = "Expect:";
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "sendfile",
CURLFORM_FILE, "/Users/xxxx/Downloads/google.jpg",
CURLFORM_END);
curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "filename",
CURLFORM_COPYCONTENTS, "/Users/xxxx/Downloads/google.jpg",
CURLFORM_END);
headerlist = curl_slist_append( headerlist, "X-Parse-Application-Id: xxxxxxx");
headerlist = curl_slist_append( headerlist, "X-Parse-REST-API-Key: xxxxxxxx");
headerlist = curl_slist_append( headerlist, "Content-Type: image/jpeg");
headerlist = curl_slist_append(headerlist, buf);
curl = curl_easy_init();
if(curl)
{
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_URL, "https://api.parse.com/1/files/pic.jpg");
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
res = curl_easy_perform(curl);
if(res != CURLE_OK){
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
the output is,
{"url":"http://files.parsetfss.com/3603be25-6ce1-4ee5-ba97-0fad4406d6cc/tfss-c7432593- bd61-424b-8a84-41308045040d-pic.jpg","name":"tfss-c7432593-bd61-424b-8a84-41308045040d-pic.jpg"}
but url contains no image, do i need do change anything?
second question is how do i access these url and name in the code?
The problem is you perform a multipart/form-data POST (adapted from this sample) where the Parse API expects a regular HTTP POST, i.e simply post the binary data (= image file content) as body.
To solve your problem you can use CURLOPT_POST and provide the file content as described by the official file upload sample, i.e:
FILE *fd = fopen("/path/to/image.jpg", "rb");
struct stat file_info;
fstat(fileno(fd), &file_info);
/* ... */
curl_easy_setopt(curl, CURLOPT_URL, "https://api.parse.com/1/files/pic.jpg");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_READDATA, fd);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (curl_off_t)file_info.st_size);
And keep the header list as is.
See CURLOPT_POST for alternatives on how to pass the binary data.
- First you need to initilise curl * variable ; put image on c drive
to upload; declare post * variable ; add post variable in curl_formadd
if (curl)
{
curl_formadd(&post, &last,
CURLFORM_COPYNAME, "image",
CURLFORM_FILE, "C://bubble.jpg",
CURLFORM_END);
curl_formadd(&post, &last,
CURLFORM_COPYNAME, "image",
CURLFORM_COPYCONTENTS, "C://bubble.jpg",
CURLFORM_END);
/////////////////////////////////////////////////////////////////////
curl_formadd(&post, &last,
CURLFORM_COPYNAME, "key",
CURLFORM_COPYCONTENTS, "1748ee815be8f13cea057a29a7ec47ee",
CURLFORM_END);
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost//nutircsupload//simpleupload.php");
curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writeCallback);
res = curl_easy_perform(curl);
if (res)
{
return 0;
}
curl_formfree(post);
}