PHP 5.6 发送 FormData 必须用 CURLFile 类替代已废弃的 @语法,正确传入绝对路径、MIME 类型和文件名,并通过关联数组提交以自动设置 multipart/form-data;手动设 Content-Type 或错配字段名会导致解析失败。

PHP 5.6 发送 FormData(即 multipart/form-data)的核心是正确构造带文件和字段的 POST 请求,关键不在“怎么发”,而在于“服务端能不能识别并解析”。PHP 5.6 起已**彻底废弃 @/path/to/file 语法**,必须改用 CURLFile 类,否则上传会静默失败——这是最常踩的坑。
必须用 CURLFile 构造文件字段
老写法 ['file' => '@/tmp/a.jpg'] 在 PHP 5.6+ 不生效,cURL 会把字符串当普通文本传过去,后端收不到文件内容。
- 正确方式:实例化
CURLFile,三个参数缺一不可:new CURLFile('/tmp/a.jpg', 'image/jpeg', 'a.jpg') - 第一个参数是服务器上真实存在的**绝对路径**;
- 第二个参数是 MIME 类型,不能瞎填,建议用
finfo_file(finfo_open(FILEINFO_MIME_TYPE), $path)动态获取; - 第三个参数是上传后在
$_FILES['file']['name']中显示的文件名,影响后端扩展名校验(比如服务端只允许.png,这里就得填a.png)。
数组传给 CURLOPT_POSTFIELDS 就自动走 multipart
cURL 会根据 CURLOPT_POSTFIELDS 的值类型自动决定 Content-Type:
- 传关联数组 + 含
CURLFile实例 → 自动设为multipart/form-data,并生成 boundary; - 不要手动设置
Content-Type: multipart/form-data,否则会冲突,导致服务端解析失败; - 字段名(如
'photo')必须和服务端接收的$_FILES['photo']完全一致; - 可同时混传普通字段:
['photo' => $file, 'title' => '封面图', 'type' => 'avatar'],这些会作为 form 字段出现在请求体中。
务必检查基础配置和调试开关
很多 400 或空 $_FILES 问题其实和文件无关,而是请求没发对。
立即学习“PHP免费学习笔记(深入)”;
- 必须设
CURLOPT_POST => true,且不能设CURLOPT_CUSTOMREQUEST(会覆盖 POST 方法); - 必须设
CURLOPT_RETURNTRANSFER => true,否则curl_exec()返回true而不是响应内容; - 调试时开启
CURLOPT_HEADER => true,看响应头里有没有Content-Length: 0或连接被提前关闭; - 服务端加一行日志:
file_put_contents('/tmp/upload.log', print_r($_FILES, 1), FILE_APPEND),确认是不是 PHP 层根本没收到。
上传多个文件的写法
前端用 <input name="images[]" type="file" multiple>,后端 PHP 5.6 侧要分别创建多个 CURLFile 实例:
- 不能直接传
['images[]' => [$file1, $file2]]; - 要展开成键值对:
['images[0]' => $file1, 'images[1]' => $file2]; - 或者更稳妥的做法:用循环构建数组,确保每个文件对应独立字段名;
- 服务端接收时,
$_FILES['images']是多维数组,需按标准方式遍历处理。



















