如何设置多个内容类型?

时间:2011-12-22 03:41:01

标签: php curl

如何设置多个内容类型?我必须传递一个数组来请求正文。该数组包含文本和二进制图像。

curl_setopt($apiCon, CURLOPT_POSTFIELDS, array(
    'status' => rawurlencode($status), 
    'photo' => $photoInBinary
));
curl_setopt($apiCon, CURLOPT_HTTPHEADER, array(
    'Host: api.mixi-platform.com', 
    'Authorization: OAuth ' . $accessToken, 
    'Content-Type: multipart/form-data'
));

问题是主机不了解图像的格式,所以我需要传递更多内容类型'image / jpg',但我不知道放在哪里。

以上代码有效,但只发布状态。

更新 好的,我的目标是将带有照片的状态发布到社交网络页面。

有关更多信息,请阅读: http://developer.mixi.co.jp/en/connect/mixi_graph_api/mixi_io_spec_top/voice-api/#toc-10

这是我的代码。它有效,但只发布状态,而不是照片。

    $apiCon = curl_init(self::API_POST_STATUS_WITH_PHOTO);
    curl_setopt($apiCon, CURLOPT_CONNECTTIMEOUT, 30);
    curl_setopt($apiCon, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($apiCon, CURLOPT_POST, true);
    curl_setopt($apiCon, CURLOPT_POSTFIELDS, array('status' => rawurlencode($status), 'photo' => $photoInBinary));
    curl_setopt($apiCon, CURLOPT_HTTPHEADER, array('Host: api.mixi-platform.com', 'Authorization: OAuth ' . $accessToken, 'Content-Type: multipart/form-data'));
    $result = curl_exec($apiCon);        
    curl_close($apiCon);

1 个答案:

答案 0 :(得分:1)

首先尝试不编码您的状态字段(即删除rawurlencode)。这是一个双重编码,可能这就是你的主人抱怨的原因。

(另外,您不需要显式设置内容类型标头; CURL会这样做。)

如果这还不够,您必须重新安排使用CURL魔术文件上传机制的请求,或者您必须自己构建整个multipart / form-data字符串。

这就是CURL魔术文件机制的工作原理(从文档到CURLOPT_POSTFIELDS

  

要在HTTP“POST”操作中发布的完整数据。要发布文件,请在文件前加上@并使用完整路径。可以通过使用格式为'; type = mimetype'的类型的文件名来明确指定文件类型。此参数可以作为urlencoded字符串传递,如'para1 = val1& para2 = val2& ...',或者作为一个数组,字段名称为键,字段数据为值。如果value是数组,则Content-Type标头将设置为multipart / form-data。从PHP 5.2.0开始,如果使用@前缀将文件传递给此选项,则value必须是数组。

使用CURL在multipart / form-data POST中传递特定字段的content-type的唯一方法是使用以下字段值的语法:@filepath;type=mime/type

如果$photoInBinary在文件中开始生效,只需将上述格式的文件名传递给CURL,而不是打开文件并读取数据。

但是,如果您自己在内存中创建了照片,则需要将其写入临时文件。以下是如何做到这一点:

function curlFileUploadData($data, $type='') {
    // $data can be a string or a stream
    $filename = tempnam(sys_get_temp_dir(), 'curlupload-');
    file_put_contents($filename, $data);
    $curlparam = "@{$filename}";
    if ($type) {
        $curlparam .= ";type={$type}";
    }
    return array($curlparam, $filename);
}

list($curlparam, $tmpfile) = curlFileUploadData('thedata', 'image/bmp');

// You can see the raw bits CURL sends if you run 'nc -l 9999' at a command line first
$c = curl_init('http://localhost:9999');
curl_setopt($c, CURLOPT_POSTFIELDS, array('status' => 'good', 'photo' => $curlparam));
curl_exec($c);
curl_close($c);

unlink($tmpfile); // REMEMBER TO DO THIS!!!!

请注意,CURL将在多部分文件上载中设置filename参数。确保主机不会将此用于任何重要的事情。据我所知,没有办法覆盖CURL发送的文件名 - 它将永远是给定的。

如果您不想创建临时文件并且必须使用CURL,则必须在内存中将整个multipart / form-data主体创建为字符串,并将其作为字符串提供给{{1并手动将内容类型标头设置为CURL_POSTFIELDS。这留给读者练习。到目前为止,您应该考虑使用HTTP extension,甚至multipart/form-datafopen来设置http方法和标题。