3

Im currently working with some kind of API. I have wrote simple functions which allows me to add new content, however Im stuck on uploading images.

Here's simple CURL command in documentation:

curl -v -s -u username:password \
  -H "Content-Type: multipart/form-data" \
  -H "Accept: application/api+json" \
  -F "[email protected];type=image/jpeg" \
  -F "[email protected];type=image/jpeg" \
  -XPUT ''

And a sample REQUEST:

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

Now, there is my function:

$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";

}

Finally, the response is:

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

What Im doing wrong? Any ideas? Thank you kindly for any help.

1
  • I just registered for this: thank you so much for you solution! I was stuck the same way :) :) Commented Dec 2, 2017 at 14:02

2 Answers 2

2

After several approaches using curl_file_create without getting it to work. I think the mobile.de-API is just implemented badly.

I ended up implementing a custom routine for CURLOPT_POSTFIELDS that is creating the complete multipart manually. I borrowed most of the code from the PHP manpage as "The CURLFile class".

  1. Create an array of the filenames
  2. Create multipart header (see code below)

    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);    
    }
    
  3. Use that function ;)

    $postfields = $this->curl_custom_postfields($files);
    
  4. Add boundary to http header

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

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

It's not the cleanest solution at all so please use it with care. But at least it works.

Sign up to request clarification or add additional context in comments.

Comments

0

I have the same problem and found a solution but only for single images. The trick is that your array MUST look like these:

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

That means that the the key must be "image" and nothing other! I hope that helps ;)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.