C – Sends an image from the gchar buffer (libcurl) to the ftp server

Sends an image from the gchar buffer (libcurl) to the ftp server… here is a solution to the problem.

Sends an image from the gchar buffer (libcurl) to the ftp server

I’m developing a linux application written in C that processes gdk pixbuf images and should then send them to a remote server via ftp (libcurl). The image is saved to a gchar buffer gdk_pixbuf_ save_to_buffer .

The problem is that I don’t know how to compare the data in this buffer with libcurl read callback function Used in conjunction to correctly send images to a remote server. All my attempts so far have generated random bytes in the generated file.

There is an example of a libcurl read callback function as follows:

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
{
    size_t retcode = fread(ptr, size, nmemb, stream);
    return retcode;
} 

I need to do my own callback function, take a gchar buffer instead of a file stream as input, and read the size*nmemb byte from it and store it to *ptr.

This is > to my related…

read_callback() is a function called by CURL when it needs to get the data to upload to the server. Suppose read_callback() is similar to fread(). When called, it performs whatever witchcraft giant is needed, but the final uploadable data must be stored in the *ptr buffer, which is the internal buffer of curl. For your memory buffer memcpy() will work fine as the body of read_callback(), so you don’t need real fread() at all.

size * nmemb tells you how large a buffer curl reserves for a single block of data. The last void* is a pointer set by the CURLOPT_READDATA option – it’s a freewheeling pointer, so it can point to a structure that contains the data you’re uploading and some additional information, such as current progress.

You can use it as an example:

#include <gdk-pixbuf/gdk-pixbuf.h>
#include <stdlib.h>
#include <curl/curl.h>
#include <string.h>

struct transfer
{
    gchar *buf;
    gsize total;
    size_t uploaded;
};

static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *data)
{
    struct transfer * tr = data;
    size_t left = tr->total - tr->uploaded;
    size_t max_chunk = size * nmemb;
    size_t retcode = left < max_chunk ? left : max_chunk;

memcpy(ptr, tr->buf + tr->uploaded, retcode);  <-- voodoo-mumbo-jumbo :-)

tr->uploaded += retcode;   <-- save progress
    return retcode;
} 

int main()
{
    GdkPixbuf * gbuffer = NULL;
    GError * error = NULL;
    gchar * buffer;
    gsize size;
    g_type_init();
    gbuffer = gdk_pixbuf_new_from_file("g.png", &error);
    gdk_pixbuf_save_to_buffer(gbuffer, &buffer, &size, "jpeg", &error, NULL);

struct transfer tr = {buffer, size, 0};

CURL *easyhandle = curl_easy_init();
    curl_easy_setopt(easyhandle, CURLOPT_READFUNCTION, read_callback); 
    curl_easy_setopt(easyhandle, CURLOPT_READDATA, &tr);  <-- this will be *data in read_callback()
    curl_easy_setopt(easyhandle, CURLOPT_UPLOAD, 1L); 
    curl_easy_setopt(easyhandle, CURLOPT_URL, "http://example.com/upload.php");
    CURLcode rc = curl_easy_perform(easyhandle);
}