uploading image to Parse server using libcurl in c++ - 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);
}

Related

Sending a file via multipart using libcurl in 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;
}

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;
}

Uploading a picture to a Password Protected Directory using libcurl and C++

I'm trying to upload pictures using c++ application with libcurl to my server, the file in my server is a protected directory, I tried everything I know but it didn't work.
struct curl_slist *headerlist = NULL;
const char * Picture = "C:\xxxx";
FILE *fd = fopen(Picture, "rb");
struct stat file_info;
fstat(fileno(fd), &file_info);
headerlist = curl_slist_append(headerlist, "user : xxxx");
headerlist = curl_slist_append(headerlist, "password : xxxxx");
headerlist = curl_slist_append(headerlist, "Content-Type: image/jpeg");
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, "http://xxxx.000webhostapp.com/Pictures");
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);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
MessageBox::Show("Picture Failed");
}
curl_easy_cleanup(curl);
curl_global_cleanup();
user and password are not HTTP headers, so you should not be passing them via CURLOPT_HTTPHEADER. Use CURLOPT_USERNAME and CURLOPT_PASSWORD instead. Also look at CURLOPT_HTTPAUTH.
Try this:
curl_global_init(CURL_GLOBAL_ALL);
...
const char *Picture = "C:\\xxxx";
FILE *fd = fopen(Picture, "rb");
if (!fd)
{
MessageBox::Show("Cannot Open Picture File");
}
else
{
struct stat file_info;
fstat(fileno(fd), &file_info);
curl = curl_easy_init();
if (!curl)
{
MessageBox::Show("Cannot Initialize CURL Session");
}
else
{
struct curl_slist *headerlist = curl_slist_append(NULL, "Content-Type: image/jpeg");
curl_easy_setopt(curl, CURLOPT_URL, "http://xxxx.000webhostapp.com/Pictures");
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_easy_setopt(curl, CURLOPT_USERNAME, "xxxx");
curl_easy_setopt(curl, CURLOPT_PASSWORD, "xxxxx");
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);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
MessageBox::Show("Picture Failed");
}
curl_easy_cleanup(curl);
}
fclose(fd);
}
...
curl_global_cleanup();

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);

SoundCloud Desktop App & LibCurl: How to Upload a File?

I am having serious difficulty uploading a file to an authenticated user's account on SoundCloud with LibCurl.
I've gotten as far as getting the following error message from a set of JSON-formatted string (thanks to a debug callback through LibCurl); '"error_message": "Couldn't upload that file, sure they're valid soundfiles?""?'.
The files I have been testing with are of the simplest form, created by various DAWs: PCM Wave, mono and stereo, varying lengths but short (several seconds at the most - for fast testing purposes), 44.1 kHz sampling rate and 16-bit depth. Also, I can upload them through the browser on the SoundCloud site, without complaints...
Is anybody able to take a look at the code below to help pinpoint the issue?
CURL* handle = curl_easy_init();
curl_slist* headers = nullptr;
curl_httppost* formPost = nullptr;
curl_httppost* lastPtr = nullptr;
curl_easy_setopt (handle, CURLOPT_URL, "https://api.soundcloud.com/tracks.json");
curl_easy_setopt (handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt (handle, CURLOPT_CAINFO, "(absolute path)/cacert.pem");
curl_easy_setopt (handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t) -1);
headers = curl_slist_append (headers, "Expect: 100-continue");
headers = curl_slist_append (headers, "Content-type: multipart/form-data");
curl_formadd (&formPost,
&lastPtr,
CURLFORM_COPYNAME, "oauth_token",
CURLFORM_COPYCONTENTS, /*token*/,
CURLFORM_END);
curl_formadd (&formPost,
&lastPtr,
CURLFORM_COPYNAME, "track[asset_data]",
CURLFORM_COPYCONTENTS, "Tone.wav",
CURLFORM_END);
curl_formadd (&formPost,
&lastPtr,
CURLFORM_COPYNAME, "track[title]",
CURLFORM_COPYCONTENTS, "Tone",
CURLFORM_END);
curl_formadd (&formPost,
&lastPtr,
CURLFORM_COPYNAME, "track[sharing]",
CURLFORM_COPYCONTENTS, "public",
CURLFORM_END);
curl_formadd (&formPost,
&lastPtr,
CURLFORM_COPYNAME, "Tone.wav",
CURLFORM_FILE, "C:/440 Hz Tone - 3 Seconds.wav",
CURLFORM_END);
curl_easy_setopt (handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt (handle, CURLOPT_HTTPPOST, formPost);
curl_easy_setopt (handle, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t) /* size of file in bytes */);
curl_easy_setopt (handle, CURLOPT_VERBOSE, (long) 1);
curl_easy_setopt (handle, CURLOPT_DEBUGFUNCTION, /*debug function*/);
curl_easy_setopt (handle, CURLOPT_NOPROGRESS, (long) 0);
curl_easy_setopt (handle, CURLOPT_PROGRESSFUNCTION, /*debug progress function*/);
curl_easy_perform (handle);
curl_easy_cleanup (handle);
curl_formfree (formPost);
curl_slist_free_all (headers);
Being new to this stuff, I didn't understand that the variable "track[asset_data]" is supposed to contain the local file path. Here's the fixed code;
CURL* handle = curl_easy_init();
curl_slist* headers = nullptr;
curl_httppost* formPost = nullptr;
curl_httppost* lastPtr = nullptr;
curl_easy_setopt (handle, CURLOPT_URL, "https://api.soundcloud.com/tracks.json");
curl_easy_setopt (handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt (handle, CURLOPT_CAINFO, "(absolute path)/cacert.pem");
curl_easy_setopt (handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t) -1);
headers = curl_slist_append (headers, "Expect: 100-continue");
headers = curl_slist_append (headers, "Content-type: multipart/form-data");
curl_formadd (&formPost,
&lastPtr,
CURLFORM_COPYNAME, "oauth_token",
CURLFORM_COPYCONTENTS, /*token*/,
CURLFORM_END);
curl_formadd (&formPost,
&lastPtr,
CURLFORM_COPYNAME, "track[title]",
CURLFORM_COPYCONTENTS, "Tone",
CURLFORM_END);
curl_formadd (&formPost,
&lastPtr,
CURLFORM_COPYNAME, "track[sharing]",
CURLFORM_COPYCONTENTS, "public",
CURLFORM_END);
curl_formadd (&formPost,
&lastPtr,
CURLFORM_COPYNAME, "track[asset_data]",
CURLFORM_FILE, "C:/440 Hz Tone - 3 Seconds.wav",
CURLFORM_END);
curl_easy_setopt (handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt (handle, CURLOPT_HTTPPOST, formPost);
curl_easy_setopt (handle, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t) /* size of file in bytes */);
curl_easy_setopt (handle, CURLOPT_VERBOSE, (long) 1);
curl_easy_setopt (handle, CURLOPT_DEBUGFUNCTION, /*debug function*/);
curl_easy_setopt (handle, CURLOPT_NOPROGRESS, (long) 0);
curl_easy_setopt (handle, CURLOPT_PROGRESSFUNCTION, /*debug progress function*/);
curl_easy_perform (handle);
curl_easy_cleanup (handle);
curl_formfree (formPost);
curl_slist_free_all (headers);