PHP CURL上传至Google Cloud Storage遇问题:文件上传后为0字节
解决PHP CURL上传文件为空(0字节)的问题
问题根源分析
你当前用的Postman生成代码里,CURLOPT_POSTFIELDS是硬编码的空文件内容——只有表单边界和文件元信息,完全没有实际的文件二进制数据,所以上传后自然是0字节的空文件。要解决这个问题,我们需要动态读取本地文件并正确构造multipart/form-data请求。
推荐方案:使用PHP CURLFile类(PHP 5.5+)
这是PHP官方推荐的文件上传处理方式,能自动处理边界、文件内容和头信息,避免手动构造出错:
<?php // 替换成你实际要上传的本地文件路径 $filePath = '/path/to/your/current-logo.png'; // 先检查文件是否存在且可读 if (!file_exists($filePath) || !is_readable($filePath)) { die("错误:目标文件不存在或无法读取"); } $curl = curl_init(); // 用CURLFile构造文件上传参数,自动处理MIME类型和文件名 $postFields = array( 'filename' => new CURLFile($filePath, mime_content_type($filePath), 'current-logo.png') ); curl_setopt_array($curl, array( CURLOPT_URL => "http://acquired-backup-198200.appspot.com/upload?uname=arun@gmail.com", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => $postFields, // 不需要手动设置Content-Type,CURL会自动生成正确的multipart/form-data头 CURLOPT_HTTPHEADER => array( "Cache-Control: no-cache" // 移除Postman-Token,这只是测试用头,线上不需要 ), )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL错误 #: " . $err; } else { echo $response; } ?>
兼容老版本PHP(<5.5)的方案
如果你的PHP版本低于5.5,可以手动构造multipart/form-data请求体,但要注意正确读取文件内容:
<?php $filePath = '/path/to/your/current-logo.png'; if (!file_exists($filePath) || !is_readable($filePath)) { die("错误:目标文件不存在或无法读取"); } // 生成随机边界字符串,避免和文件内容冲突 $boundary = '----WebKitFormBoundary' . uniqid(mt_rand(), true); $fileContent = file_get_contents($filePath); $mimeType = mime_content_type($filePath); // 手动构造POST请求体,包含实际文件内容 $postBody = "--$boundary\r\n" . "Content-Disposition: form-data; name=\"filename\"; filename=\"current-logo.png\"\r\n" . "Content-Type: $mimeType\r\n\r\n" . $fileContent . "\r\n" . "--$boundary--\r\n"; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "http://acquired-backup-198200.appspot.com/upload?uname=arun@gmail.com", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => $postBody, CURLOPT_HTTPHEADER => array( "Cache-Control: no-cache", "Content-Type: multipart/form-data; boundary=$boundary" ), )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL错误 #: " . $err; } else { echo $response; } ?>
关键注意事项
- 如果是前端用户上传的文件,要先通过
$_FILES获取服务器临时文件路径(比如$_FILES['user_upload']['tmp_name']),再传入代码中使用。 - 确保服务器对目标文件路径有读取权限,否则会出现文件无法读取的错误。
- 优先使用CURLFile方案,代码更简洁且不易出错,同时支持大文件上传(避免
file_get_contents读取大文件占用过多内存)。
内容的提问来源于stack exchange,提问作者alaa nabawy
相关产品推荐
相关产品推荐

