使用curl以multipart/form-data形式发布原始图像数据

39

我想在PHP中使用multipart/form-data头部使用cURL发布图像,因为接收方API希望图像作为多部分表单发送。

我没有问题与API进行其他请求的通信;只有发布图像是个问题。

我在客户端使用这个表单:

<form action="http://myServerURL" method="POST" enctype="multipart/form-data">
    <input type="file" name="file" />
    <input type="Submit">
</form>

以下是我正在向其发布此数据(在此我正尝试将此数据转发到API)的服务器:

$ch = curl_init($url);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $imgRawData); // <-- raw data here hm?
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt ($ch, CURLOPT_COOKIEFILE, $cookieJar);
curl_setopt( $ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLINFO_HEADER_OUT, 1); <-- using this as I wanted to check if HTTPHEADER is set
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data')); <-- setting content-type header?
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1);

// i get response from the server
$response = curl_exec( $ch );

// with this I can check what kind of content type the last request had?
$requestContentType = curl_getinfo($ch,CURLINFO_CONTENT_TYPE);
echo "<br>request Content Type was:".$requestContentType."<br>";    

curl_close($ch);

echo "<br><b>SERVER POST IMAGE RESPONSE:</b><br>";
echo $response;

使用下面的代码,我可以查看我的请求头:

curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);

var_dump(curl_getinfo($ch));

现在请求头中的内容类型已经正确显示。但是似乎图像未按API预期正确发送。不幸的是,我没有访问API的权限...

非常感谢您的任何帮助。


1
请检查此网址:http://www.php-guru.in/2013/upload-files-using-php-curl/ - PravinS
这经过一些关于我的结构等方面的小修改后就能正常工作了。如果您愿意,可以将其发布为答案。 - trainoasis
如果它对你有用,那就没问题了 :) - PravinS
3个回答

75

从PHP 5.6开始,在没有设置CURLOPT_SAFE_UPLOAD的情况下,@$filePathCURLOPT_POSTFIELDS中将无法工作,并且在PHP 7中完全被删除。您需要使用一个CurlFile对象,有关RFC的信息在这里

$fields = [
    'name' => new \CurlFile($filePath, 'image/png', 'filename.png')
];
curl_setopt($resource, CURLOPT_POSTFIELDS, $fields);

1
这对我非常有用,引导我不再在我的项目中使用@,而是使用CurlFile。谢谢! - David Refoua

27

如果有人遇到同样的问题:请检查@PravinS建议的这个网站。我使用了该网站上显示的完全相同的代码,它完美地为我工作。

这是帮助解决问题的服务器代码的相关部分:

if (isset($_POST['btnUpload']))
{
$url = "URL_PATH of upload.php"; // e.g. http://localhost/myuploader/upload.php // request URL
$filename = $_FILES['file']['name'];
$filedata = $_FILES['file']['tmp_name'];
$filesize = $_FILES['file']['size'];
if ($filedata != '')
{
    $headers = array("Content-Type:multipart/form-data"); // cURL headers for file uploading
    $postfields = array("filedata" => "@$filedata", "filename" => $filename);
    $ch = curl_init();
    $options = array(
        CURLOPT_URL => $url,
        CURLOPT_HEADER => true,
        CURLOPT_POST => 1,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_POSTFIELDS => $postfields,
        CURLOPT_INFILESIZE => $filesize,
        CURLOPT_RETURNTRANSFER => true
    ); // cURL options
    curl_setopt_array($ch, $options);
    curl_exec($ch);
    if(!curl_errno($ch))
    {
        $info = curl_getinfo($ch);
        if ($info['http_code'] == 200)
            $errmsg = "File uploaded successfully";
    }
    else
    {
        $errmsg = curl_error($ch);
    }
    curl_close($ch);
}
else
{
    $errmsg = "Please select the file";
}
}

HTML表单应该长成这个样子:

<form action="uploadpost.php" method="post" name="frmUpload" enctype="multipart/form-data">
<tr>
  <td>Upload</td>
  <td align="center">:</td>
  <td><input name="file" type="file" id="file"/></td>
</tr>
<tr>
  <td>&nbsp;</td>
  <td align="center">&nbsp;</td>
  <td><input name="btnUpload" type="submit" value="Upload" /></td>
</tr>

1
那么,哪部分代码解决了你遇到的问题?发布相关的代码片段将有助于遇到相同问题的其他人。(特别是如果那个链接失效或更改) - Leigh
为什么人们不使用CURLFile函数?我正在尝试使用它,但它不起作用,我也找不到带有它使用的工作代码片段。你是故意忽略了CURLFile类吗? - Erik
4
@Erik,CURLFile类需要PHP 5.5或更高版本。由于当前Debian稳定版(目前为wheezy)默认使用的是PHP 5.4,因此无法使用CURLFile类。 - MukMuk

0

在PHP中使用多部分/表单数据实现服务器之间的CURL操作,无需HTML表单

// 要上传的文件

$filename = "https://example.s3.amazonaws.com/0.jpg";       

// 上传到的URL(目标服务器)

$url = "https://otherserver/image";

并且

    $curl = curl_init();

    curl_setopt_array($curl, array(
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 30,
        //CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST => "POST",
        CURLOPT_POST => 1,
        CURLOPT_POSTFIELDS => file_get_contents($filename),
        CURLOPT_HTTPHEADER => array(
            //"Authorization: Bearer $TOKEN",
            "Content-Type: multipart/form-data",
            "Content-Length: " . strlen(file_get_contents($filename)),
            "API-Key: abcdefghi" //Optional if required
        ),
    ));

   $response = curl_exec($curl);

    $info = curl_getinfo($curl);
//echo "code: ${info['http_code']}";

//print_r($info['request_header']);

    var_dump($response);
    $err = curl_error($curl);

    echo "error";
    var_dump($err);
    curl_close($curl);

几乎可以工作了...我得到了一个错误:在未知的第0行中,multipart/form-data POST数据中缺少边界。 - Chololoco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接