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

如何用curl通过标准multipart-form-data请求收发文件?相关疑问求解

用cURL发送/接收multipart-form-data格式文件的完整方案

我来帮你理清这个问题——其实核心是新老API的兼容性和安全性问题,下面一步步给你讲清楚:

为什么大家都用CurlFile/curl_file_create()?

你提到的老@语法在PHP 5.5之后就被官方废弃了,而且从PHP 5.5开始,CURLOPT_SAFE_UPLOAD选项默认是开启的,这时候@会被当成普通字符串处理,根本不会触发文件上传逻辑。用CurlFile是官方推荐的标准方式,不仅能避免这个问题,还能更清晰地指定文件的MIME类型和表单显示文件名,同时也更安全,能防止恶意构造的字符串被当成文件路径解析。

发送文件的完整代码示例

1. PHP 5.5+ 推荐写法(绝大多数场景用这个)

// 你的文件路径
$filePath = 'unit.txt';

// 创建CurlFile对象:参数分别是文件路径、MIME类型(可选,自动检测的话可以传null)、表单里的文件名(可选,默认用原文件名)
$cFile = curl_file_create($filePath, 'text/plain', 'uploaded_unit.txt');

// 组装POST数据,这里的'file'是表单字段名,后端接收时要对应这个key
$postData = [
    'file' => $cFile,
    'description' => '这是一个测试文本文件' // 可以加其他表单字段
];

// 初始化cURL会话
$ch = curl_init();

// 配置请求参数
curl_setopt($ch, CURLOPT_URL, 'https://你的上传接口地址.com/upload'); // 替换成你的实际接口
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 让curl返回响应内容而不是直接输出

// 如果是测试环境的HTTPS接口,暂时关闭SSL验证(生产环境一定要去掉这行,确保证书有效)
// curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

// 执行请求并获取结果
$response = curl_exec($ch);

// 检查请求是否出错
if (curl_errno($ch)) {
    die('cURL请求出错:' . curl_error($ch));
}

// 关闭cURL资源
curl_close($ch);

// 处理响应
var_dump($response);

2. 兼容PHP 5.5以下的写法(不推荐,仅作应急)

如果你的项目还在维护非常老的PHP版本,需要关闭CURLOPT_SAFE_UPLOAD才能用老语法,但注意这个选项在PHP 7.0之后被移除了,所以能升级的话尽量升级:

$filePath = 'unit.txt';
$realFilePath = realpath($filePath); // 确保路径是绝对路径

$postData = [
    'file' => "@{$realFilePath};filename=uploaded_unit.txt;type=text/plain",
    'description' => '测试文件'
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://你的上传接口地址.com/upload');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false); // 必须关闭这个选项,否则@会被当成字符串
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);

if (curl_errno($ch)) {
    die('cURL请求出错:' . curl_error($ch));
}

curl_close($ch);

var_dump($response);

后端接收文件的示例(PHP)

如果是你自己写后端接口接收,代码大概是这样:

// 检查是否有合法的文件上传
if (isset($_FILES['file']) && $_FILES['file']['error'] === UPLOAD_ERR_OK) {
    $uploadedFile = $_FILES['file'];
    $tmpFile = $uploadedFile['tmp_name']; // 服务器上的临时文件路径
    $targetDir = './uploads/'; // 目标保存目录,要确保有写入权限
    $targetFile = $targetDir . basename($uploadedFile['name']);

    // 创建目标目录(如果不存在)
    if (!is_dir($targetDir)) {
        mkdir($targetDir, 0755, true);
    }

    // 移动临时文件到目标目录
    if (move_uploaded_file($tmpFile, $targetFile)) {
        echo json_encode([
            'status' => 'success',
            'message' => '文件上传成功',
            'file_path' => $targetFile
        ]);
    } else {
        echo json_encode([
            'status' => 'error',
            'message' => '无法保存上传的文件,请检查目录权限'
        ]);
    }
} else {
    $errorMsg = $_FILES['file']['error'] ? '错误码:' . $_FILES['file']['error'] : '没有上传文件';
    echo json_encode([
        'status' => 'error',
        'message' => '文件上传失败:' . $errorMsg
    ]);
}

常见坑点排查

  • 确保前端的表单字段名(比如示例里的file)和后端$_FILES的key完全一致,否则接收不到文件
  • 检查PHP配置:upload_max_filesize和post_max_size要大于你上传的文件大小,不然会被PHP拦截
  • HTTPS请求时,尽量不要关闭CURLOPT_SSL_VERIFYPEER,如果测试环境必须关,生产环境一定要配置正确的CA证书
  • 如果用框架的话,有些框架会对multipart请求有特殊处理,比如Laravel需要确保请求是正确的POST方法,并且没有开启CSRF验证(或者在请求里带上CSRF令牌)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:47:54