伟明部落格

C语言使用libcurl库上传文件

--发布于 2023-03-07 20:01:05

使用curl-7.77.0这个版本的库

将文件Arturo_Ricci_The_recital.jpg上传到网址https://snailpad.cn/simple-fileupload/upload.php,其中文件内容放置到字段snailpad_file,文件的md5值(预先算好)放置到md5字段。上传的应答结果由名为cb的函数处理。

#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 待上传文件的文件名
const char *filename = "Arturo_Ricci_The_recital.jpg";

/**
 * @brief 用于存储libcurl应答数据
 */
struct memory {
    char *response; // 数据内容
    size_t size; // 数据长度
};

/**
 * @brief libcurl应答的回调函数(参考:https://curl.se/libcurl/c/CURLOPT_WRITEFUNCTION.html)
 * @param data
 * @param size
 * @param nmemb
 * @param userp
 * @return
 */
static size_t cb(void *data, size_t size, size_t nmemb, void *userp)
{
    size_t realsize = size * nmemb;
    struct memory *mem = (struct memory *)userp;

    char *ptr = (char *) realloc(mem->response, mem->size + realsize + 1);
    if(ptr == NULL)
        return 0;  /* out of memory! */

    mem->response = ptr;
    memcpy(&(mem->response[mem->size]), data, realsize);
    mem->size += realsize;
    mem->response[mem->size] = 0;

    return realsize;
}

int main(int argc, char *argv[])
{
    // 加载文件数据
    FILE *fp = fopen(filename, "rb");
    if (fp == NULL) {
        printf("Error!fopen() failed, filename[%s]\n", filename);
        return -1;
    }

    // 获取文件大小
    fseek(fp, 0, SEEK_END);
    long file_len = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    // 读取文件内容
    unsigned char *buffer = (unsigned char *) calloc(1, file_len);
    fread(buffer,1, file_len, fp);
    fclose(fp);

    struct memory chunk = {0};

    CURLcode res;
    CURL *curl = curl_easy_init();

    if (curl == NULL) {
        printf("Error!curl_easy_init() failed\n");
        return -1;
    }

    curl_mime* form = curl_mime_init(curl);

    curl_mimepart *field = NULL;

    // 添加文件md5的Field
    field = curl_mime_addpart(form);
    curl_mime_name(field, "md5");
    curl_mime_data(field, "d82f237bd667f442972e877c9cab614e", CURL_ZERO_TERMINATED);

    // 添加文件数据字段的Field
    field = curl_mime_addpart(form);
    curl_mime_name(field, "snailpad_file"); // 就是上传文件的Key
    curl_mime_filedata(field, filename); // 文件名
    curl_mime_data(field, buffer, file_len); // 文件内容

    curl_easy_setopt(curl, CURLOPT_URL, "https://snailpad.cn/simple-fileupload/upload.php");
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);

    /* send all data to this function  */
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, cb);

    /* we pass our 'chunk' struct to the callback function */
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);

    curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);

    /* Perform the request, res will get the return code */
    res = curl_easy_perform(curl);

    if (res != CURLE_OK) {
        printf("Error!curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        return -1;
    }

    printf("size[%d]\n", chunk.size);
    printf("content[%s]\n", chunk.response);

    // 释放动态分配的内存
    free(chunk.response);

    /* always cleanup */
    curl_easy_cleanup(curl);

    /* then cleanup the form */
    curl_mime_free(form);

    return 0;
}
--更新于 2023-04-20 14:04:22