为何Postman生成的PHP cURL代码在项目中上传CSV文件失败?
问题:Postman生成的PHP cURL代码无法正确上传CSV文件到Web服务
将我通过Postman发送附带CSV文件的请求时,可正常获取Web服务的响应。但将Postman生成的PHP cURL代码整合至带有文件上传表单的项目后,收到了错误响应。Web服务似乎能接收到CSV文件,但无法正常处理,返回信息为“Upload salesquote fail”而非“No attached file part”。该错误提示与上传空CSV文件时的情况类似,但我无法确定。以下是我的代码:
if ( isset($_FILES["salesquote2"])) { $url = <service URL>; $filename = $_FILES['salesquote2']['name']; $filedata = $_FILES['salesquote2']['tmp_name']; $filesize = $_FILES['salesquote2']['size']; $storefile = __DIR__."/csvfile"."/".$filename; $storefile2 = realpath($filedata); echo '$filename = ' . $filename . "</br>"; echo '$filedata = ' . $filedata . "</br>"; echo '$filesize = ' . $filesize . "</br>"; echo $storefile . "</br>" ; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_PORT => "4546", CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"salesquote\"; filename=\"$filedata\"\r\nContent-Type: text/csv\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--", CURLOPT_HTTPHEADER => array( "Cache-Control: no-cache", "Postman-Token: 56363463-ed09-4cf0-bb91-ff546980bb98", "content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" ), )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } }
问题排查与解决方案
我一眼就发现问题所在了——Postman生成的代码手动构造了multipart/form-data的请求体,但它只是把临时文件路径填到了filename字段里,根本没把文件的实际内容写入请求中!这就导致Web服务收到的是一个空(或无效)的文件,自然返回和上传空文件一样的错误。
Postman生成的代码经常会犯这种偷懒的毛病,咱们直接用PHP cURL的原生方式处理文件上传就好,不需要手动拼接请求体。下面是修正后的代码:
if (isset($_FILES["salesquote2"])) { $url = "<service URL>"; $filename = $_FILES['salesquote2']['name']; $filedata = $_FILES['salesquote2']['tmp_name']; $filesize = $_FILES['salesquote2']['size']; // 可选:如果需要先把文件保存到服务器本地,保留这段代码;不需要的话可以删掉 $storefile = __DIR__ . "/csvfile/" . $filename; move_uploaded_file($filedata, $storefile); // 如果要转发保存后的文件,把下面的$filedata换成$storefile即可 echo '$filename = ' . $filename . "<br/>"; echo '$filedata = ' . $filedata . "<br/>"; echo '$filesize = ' . $filesize . "<br/>"; echo $storefile . "<br/>"; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_PORT => "4546", CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", // 核心修改:用数组传递表单数据,cURL会自动生成正确的multipart格式 CURLOPT_POSTFIELDS => array( 'salesquote' => new CURLFile($filedata, 'text/csv', $filename) ), CURLOPT_HTTPHEADER => array( "Cache-Control: no-cache" // 移除了Postman-Token(这是Postman的专属标识,项目里不需要) // 也删掉了手动指定的content-type,cURL会自动生成带正确boundary的头 ), )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; } }
关键修改说明:
- 使用
CURLFile类:这是PHP 5.5+推荐的文件上传方式,它会自动处理文件的MIME类型、文件名和内容,彻底避免手动构造请求体的错误。 - 移除冗余头信息:
Postman-Token是Postman的专属标识,项目里不需要保留;手动指定的content-type也删掉,因为cURL会根据你传递的数组自动生成正确的multipart/form-data头(包括boundary),手动指定反而容易导致格式不匹配。 - 可选的文件保存:如果不需要先把文件存到服务器,直接用临时文件路径
$filedata即可;如果需要保存,记得用move_uploaded_file,因为PHP的临时文件会在请求结束后自动删除。
内容的提问来源于stack exchange,提问作者stevieki
相关产品推荐
相关产品推荐

