PHP用cURL上传文件必须通过multipart/form-data POST请求,推荐使用CurlFile对象(而非已废弃的@前缀),并确保服务端正确配置upload_max_filesize、post_max_size及$_FILES解析逻辑。

PHP 用 cURL 上传文件到远程服务器,不是“打开”而是 POST 文件流
PHP 本身不能像本地那样直接 fopen("http://...") 写入远程 URL——HTTP 协议不支持远程写入,所谓“上传”必须走 POST(或 PUT)请求,由目标服务器明确提供接收接口。你看到的“curl 上传”,本质是构造一个 multipart/form-data 请求,把文件内容作为表单字段发过去。
cURL 上传时 CURLOPT_POSTFIELDS 怎么传文件
关键在是否启用 @ 前缀(PHP 5.5+ 已废弃)或改用 CurlFile 对象。旧写法(PHP CurlFile 或路径错误会导致空文件、400 Bad Request 或后端收不到 $_FILES。
远程接收端必须能解析 multipart 数据,否则上传会静默失败
接收脚本(比如 upload.php)需满足:
- 使用标准
$_FILES而非file_get_contents('php://input')(后者拿不到 multipart 文件) - 确保
post_max_size和upload_max_filesize在php.ini中足够大 - 检查
$_FILES['file']['error'] === UPLOAD_ERR_OK,别只看是否有值 - 若用 Nginx,确认没开启
client_max_body_size限制
$_FILES 为空——大概率是服务端未正确配置上传处理逻辑或大小限制卡住了。
不用 cURL 也能上传?file_put_contents 不行,stream_context_create 有局限
file_put_contents('http://...', $data) 仅支持 PUT,且要求服务端显式支持 PUT 并配置 Web 服务器允许(Apache 需 mod_dav,Nginx 默认禁用),实际极少用于文件上传。更现实的替代是:
$context = stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Content-Type: multipart/form-data; boundary=" . $boundary,
'content' => $raw_body // 手动拼接 multipart body(极容易出错)
]
]);
file_get_contents('https://api.example.com/upload', false, $context);但手动构造 multipart 太易出错,边界符、换行、编码全要自己管。不如老实用 CurlFile + cURL。
真正容易被忽略的是:上传路径是否带认证(如需 Bearer Token)、目标接口是否要求特定字段名(比如后端期待 image 而不是 file)、以及 CurlFile 的第三个参数(上传后的文件名)会影响 $_FILES['file']['name']——这关系到后端保存逻辑。没对齐就等于白传。










