You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将curl POST文件上传命令转换为libcurl代码?

问题分析与解决方案

你的核心错误是混淆了两种POST请求格式:

  • 原curl命令curl -d @path/to/data.json的作用是读取文件内容,将其作为普通POST请求的请求体(默认Content-Type为application/x-www-form-urlencoded)。
  • 而你用curl_formadd构造的是multipart/form-data类型的表单上传,这和原命令的请求格式完全不同,所以服务器返回"Bad request"。

正确的libcurl实现方式

方式一:用回调函数读取文件(适合大文件,内存友好)

这种方式不需要把整个文件读到内存,而是通过回调逐段读取:

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

// 读取文件的回调函数
size_t file_read_callback(char *ptr, size_t size, size_t nmemb, void *userdata) {
    FILE *file = (FILE *)userdata;
    return fread(ptr, size, nmemb, file);
}

int main(void) {
    CURL *curl = curl_easy_init();
    if (!curl) {
        fprintf(stderr, "Failed to initialize curl\n");
        return 1;
    }

    // 打开目标文件
    FILE *json_file = fopen("path/to/data.json", "rb");
    if (!json_file) {
        perror("Failed to open data.json");
        curl_easy_cleanup(curl);
        return 1;
    }

    // 设置请求URL
    curl_easy_setopt(curl, CURLOPT_URL, "https://reqbin.com/echo/post/json");
    // 指定为POST请求
    curl_easy_setopt(curl, CURLOPT_POST, 1L);
    // 设置读取回调和文件指针
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, file_read_callback);
    curl_easy_setopt(curl, CURLOPT_READDATA, json_file);

    // 获取文件大小并设置Content-Length(可选,但推荐,避免服务器处理异常)
    fseek(json_file, 0, SEEK_END);
    long file_size = ftell(json_file);
    fseek(json_file, 0, SEEK_SET);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)file_size);

    // 如果服务器明确要求JSON格式,添加Content-Type头部
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "Content-Type: application/json");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

    // 执行请求
    CURLcode res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
        fprintf(stderr, "Request failed: %s\n", curl_easy_strerror(res));
    }

    // 清理资源
    curl_slist_free_all(headers);
    fclose(json_file);
    curl_easy_cleanup(curl);

    return 0;
}

方式二:读取文件到内存后发送(适合小文件,代码更简洁)

如果文件不大,可以直接把内容读到内存,再通过CURLOPT_POSTFIELDS设置:

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

int main(void) {
    CURL *curl = curl_easy_init();
    if (!curl) {
        fprintf(stderr, "Failed to initialize curl\n");
        return 1;
    }

    FILE *json_file = fopen("path/to/data.json", "rb");
    if (!json_file) {
        perror("Failed to open data.json");
        curl_easy_cleanup(curl);
        return 1;
    }

    // 获取文件大小并分配内存
    fseek(json_file, 0, SEEK_END);
    long file_size = ftell(json_file);
    fseek(json_file, 0, SEEK_SET);
    char *json_data = malloc(file_size + 1);
    if (!json_data) {
        perror("Failed to allocate memory");
        fclose(json_file);
        curl_easy_cleanup(curl);
        return 1;
    }

    // 读取文件内容到内存
    fread(json_data, 1, file_size, json_file);
    json_data[file_size] = '\0'; // 确保字符串结束(可选,因为POSTFIELDSIZE已指定长度)
    fclose(json_file);

    // 设置请求参数
    curl_easy_setopt(curl, CURLOPT_URL, "https://reqbin.com/echo/post/json");
    curl_easy_setopt(curl, CURLOPT_POST, 1L);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data);
    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, file_size);

    // 添加JSON格式头部
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "Content-Type: application/json");
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

    // 执行请求
    CURLcode res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
        fprintf(stderr, "Request failed: %s\n", curl_easy_strerror(res));
    }

    // 清理资源
    curl_slist_free_all(headers);
    free(json_data);
    curl_easy_cleanup(curl);

    return 0;
}

关键注意点

  1. 如果你不需要指定Content-Type: application/json,可以去掉对应的头部设置,完全模拟原curl命令的默认行为。
  2. 务必确保文件路径正确,且程序有读取文件的权限。

内容的提问来源于stack exchange,提问作者SunriseAvenue

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 03:05:21