php curl实现 multipart/form-data 的 post 提交

php之curl 2020-01-17 阅读 2119 评论 0

php 的 curl 类库,使用表单 multipart/form-data 类型的 post 方式,不仅可以提交json和数组,也支持文件。文件的发送需要注意 php 的版本,5.5 以下可以直接在文件的路径前面加上 @ 符号,5.5 以上的需要用 CURLFile 类,或者 curl_file_create

实现代码

注意 curl_setopt($curl, CURLOPT_POST, true) 一定要放在 curl_setopt($curl, CURLOPT_POSTFIELDS, $data) 前面。不然会发送错误。

function post($url, $data, $headers)
{
    $curl = curl_init();
    curl_setopt_array($curl, array(
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true, // 如果成功只将结果返回,不自动输出任何内容
        CURLOPT_TIMEOUT => 0,   // 设置curl允许执行的最长秒数
        CURLOPT_POST => true,   // 注意 CURLOPT_POST 一定要在 CURLOPT_POSTFIELDS 前面
        CURLOPT_POSTFIELDS => $data // 请求的数据内容
    ));
    // 设置请求头
    if (!empty($headers)) {
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    }
    $response = curl_exec($curl);
    $errno = curl_errno($curl);
    if ($errno) {
        return false;
    }
    curl_close($curl);
    return $response;
}

调用示例

发送数据为 Array 格式,不需要进行 json_encode,不用指定 Content-Type,请求头Content-Type 会自动设置成 multipart/form-data。

以下是上传 bmp 格式的图片和一些文本。

$data = [
    "name" => "用户名",
    "password" => "密码",
];
$file = "/Users/apple/Downloads/201228bli.bmp";
// php 5.5+ 需要使用 curl_file_create 方法
if (function_exists('curl_file_create')) {
    $data['avatar'] = curl_file_create($file);
} else {
    $data['avatar'] = '@' . $file;
}
$headers = ["User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36"];
echo post("http://localhost/response.php", $data, $headers);

response.php 执行打印 post 值 和 Content-Type

print_r($_REQUEST);
$contentType = $_SERVER["CONTENT_TYPE"];
print_r($contentType);

输出

Array
(
    [name] => 用户名
    [password] => 密码
)
multipart/form-data; boundary=------------------------37d33deee2fc7597

以下是 phpstorm 断点调试的截图。

最后更新 2020-01-18
MIP.watch('startSearch', function (newVal, oldVal) { if(newVal) { var keyword = MIP.getData('keyword'); console.log(keyword); // 替换当前历史记录,新增 MIP.viewer.open('/s/' + keyword, {replace: true}); setTimeout(function () { MIP.setData({startSearch: false}) }, 1000); } }); MIP.watch('goHome', function (newVal, oldVal) { MIP.viewer.open('/', {replace: false}); });