CURL:将带边界的图像发送到 REST API

Posted

技术标签:

【中文标题】CURL:将带边界的图像发送到 REST API【英文标题】:CURL: Send images with boundary to REST API 【发布时间】:2017-11-09 22:31:50 【问题描述】:

我目前正在使用某种 API。我编写了简单的函数,允许我添加新内容,但我坚持上传图片。

这是文档中的简单 CURL 命令:

curl -v -s -u username:password \
  -H "Content-Type: multipart/form-data" \
  -H "Accept: application/api+json" \
  -F "image=@img1.jpeg;type=image/jpeg" \
  -F "image=@img2.jpeg;type=image/jpeg" \
  -XPUT ''

还有一个示例请求:

PUT /images HTTP/1.1
Host: example
Content-Type: multipart/form-data; boundary=vjrLeiXjJaWiU0JzZkUPO1rMcE2HQ-n7XsSx

--vjrLeiXjJaWiU0JzZkUPO1rMcE2HQ-n7XsSx
Content-Disposition: form-data; name="image"; filename="img1.jpg"
Content-Type: image/jpeg
Content-Transfer-Encoding: binary

现在,有我的功能:

$headers_put = array( 
   "Content-Type: multipart/form-data; boundary=vjrLeiXjJaWiU0JzZkUPO1rMcE2HQ-n7XsSx",
   "Accept: application/+json",  
); 

function putImages($ch, $headers, $ad, $images)
    $url = '/images';

    $files = [];

    foreach($images as $key => $image) 
        $number = $key +1;
        $paths = parse_url($image, php_URL_PATH);
        $paths = $_SERVER['DOCUMENT_ROOT'] . $paths;

        $cfile = new CURLFile(''. $paths, 'image/jpeg', 'image'.$key);
        $files[$key] = $cfile;

    

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
    curl_setopt($ch, CURLOPT_POSTFIELDS, $files);

    $result = curl_exec($ch);
    var_dump($result);

    echo curl_getinfo($ch, CURLINFO_HTTP_CODE);
    echo "\n";


最后得到的回应是:

"errors":"error":"@key":"unsupported-form-element""

我做错了什么?有任何想法吗?非常感谢您的帮助。

【问题讨论】:

我刚刚注册了这个:非常感谢您的解决方案!我被困在同样的方式:) :) 【参考方案1】:

在使用 curl_file_create 的几种方法后没有让它工作。我认为 mobile.de-API 的实现很糟糕。

我最终为 CURLOPT_POSTFIELDS 实现了一个自定义例程,该例程手动创建了完整的多部分。我从 PHP 手册页中借用了大部分代码作为“CURLFile 类”。

    创建一个文件名数组

    创建多部分标题(见下面的代码)

    function curl_custom_postfields(array $files = array())    
    
    // build file parameters
    foreach ($files as $k => $v) 
        switch (true) 
            case false === $v = realpath(filter_var($v)):
            case !is_file($v):
            case !is_readable($v):
                continue; // or return false, throw new InvalidArgumentException
        
        $data = file_get_contents($v);
        $body[] = implode("\r\n", array(
            "Content-Disposition: form-data; name=\"image\"",
            "Content-Type: image/jpeg",
            "",
            $data,
        ));
    
    
    // generate safe boundary
    do 
        $boundary = "---------------------" . md5(mt_rand() . microtime());
     while (preg_grep("/$boundary/", $body));
    
    // add boundary for each parameters
    array_walk($body, function (&$part) use ($boundary) 
        $part = "--$boundary\r\n$part";
    );
    
    // add final boundary
    $body[] = "--$boundary--";
    $body[] = "";
    
    // set options
    return array(implode("\r\n", $body), $boundary);    
    
    

    使用该功能;)

    $postfields = $this->curl_custom_postfields($files);
    

    为http头添加边界

    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data; boundary=' . $postfields[1], 'Accept: application/vnd.de.mobile.api+json'));
    

    添加邮递区

    curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields[0]);
    

这根本不是最干净的解决方案,所以请小心使用。但至少它有效。

【讨论】:

【参考方案2】:

我有同样的问题并找到了解决方案,但仅适用于单个图像。 诀窍是您的数组必须如下所示:

$images = array(
  'image' => 'PATH/IMG.jpg',
);

这意味着密钥必须是“图像”而不是其他! 我希望这会有所帮助;)

【讨论】:

以上是关于CURL:将带边界的图像发送到 REST API的主要内容,如果未能解决你的问题,请参考以下文章

文档中除了 CURL Post 示例之外的 Solace Rest API 用法或示例

Apache HTTPClient POST 到 REST 服务的方式与 cURL 不同

用于系统通知的 Quickblox REST API

无法使用 Curl 将要素类型上传到 Geoserver REST API

Node.js 通过 REST API 发送图像

QuickBlox - 如何使用 REST API + PHP 创建 blob 内容