【问题标题】:Posting raw image data as multipart/form-data in curl在 curl 中将原始图像数据作为 multipart/form-data 发布
【发布时间】:2014-02-20 11:10:24
【问题描述】:

我正在尝试使用 multipart/form-data 标头在 PHP 中发布带有 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...

感谢您的帮助,谢谢

【问题讨论】:

标签: php curl multipartform-data


【解决方案1】:

从 PHP 5.6 开始,@$filePath 将无法在没有设置 CURLOPT_SAFE_UPLOAD 的情况下在 CURLOPT_POSTFIELDS 中工作,并且在 PHP 7 中它被完全删除。您将需要使用 CurlFile 对象 RFC here。

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

【讨论】:

  • 这对我来说真的很有用,指导我在项目中不再使用@,而是使用CurlFile。谢谢!
【解决方案2】:

如果有人遇到同样的问题:按照@PravinS 的建议检查this。我使用了与那里显示的完全相同的代码,它非常适合我。

这是帮助的服务器代码的相关部分:

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>

【讨论】:

  • 那么代码的哪一部分解决了您遇到的问题?发布相关代码 sn-p 将帮助遇到同样问题的其他人。 (特别是如果该链接断开或更改)
  • 为什么人们不使用 CURLFile 函数?我正在尝试,但它不起作用,我也找不到使用它的工作代码 sn-ps。您是否故意完全忽略了 CURLFile 类?
  • @Erik CURLFile 类适用于 >= PHP 5.5。由于(在其他系统中)当前的 debian stable(此时喘不过气来)使用 PHP 5.4 开箱即用,他们不能使用 CURLFile 类。
【解决方案3】:

使用 MULTIPART/FORM-DATA 的 PHP 中没有 HTML 表单的服务器到服务器之间的 CURL 操作

//要上传的文件

$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 行的 Unknown 中得到了 Multipart/form-data POST 数据中的缺失边界
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-22
  • 2018-05-01
  • 2018-12-31
  • 2018-12-26
  • 2019-05-23
相关资源
最近更新 更多