Search code examples
phpcurllinkedin-apiphp-curl

Image upload not working in Linkedin V2 API


I'm now working with Linkedin V2 integration with my application. I'm facing an issue while trying to upload image to Linkedin.

I have tried CURL request from my terminal(I'm using Ubuntu OS) & getting response as below:

Terminal command (Working & file uploaded):

curl -i --upload-file /Users/peter/Desktop/superneatimage.png --header "Authorization: Bearer redacted" 'https://api.linkedin.com/mediaUpload/C5522AQGTYER3k3ByHQ/feedshare-uploadedImage/0?ca=vector_feedshare&cn=uploads&m=AQJbrN86Zm265gAAAWemyz2pxPSgONtBiZdchrgG872QltnfYjnMdb2j3A&app=1953784&sync=0&v=beta&ut=2H-IhpbfXrRow1'

It's response as below:

HTTP/2 201 date: Wed Apr 10 09:14:44 UTC 2019 server: Play set-cookie: lang=v=2&lang=en-us; Path=/; Domain=api.linkedin.com x-ambry-creation-time: Wed Apr 10 09:14:44 UTC 2019 access-control-allow-origin: https://www.linkedin.com content-length: 0

I'm facing issue when I integrate the CURL request in my application. My CURL request code from my application is given below.

$headers = array();
$headers[] = 'Authorization: Bearer xxxxx';
$headers[] = 'X-Restli-Protocol-Version: 2.0.0';
$headers[] = 'Content-Type: multipart/form-data';
$ch = curl_init();
$options = array(
    CURLOPT_HEADER => true,
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_URL => 'https://api.linkedin.com/mediaUpload/C5522AQGTYER3k3ByHQ/feedshare-uploadedImage/0?ca=vector_feedshare&cn=uploads&m=AQJbrN86Zm265gAAAWemyz2pxPSgONtBiZdchrgG872QltnfYjnMdb2j3A&app=1953784&sync=0&v=beta&ut=2H-IhpbfXrRow1',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => array("upload-file" => '/Users/peter/Desktop/superneatimage.png')
    // CURLOPT_POSTFIELDS => array("upload-file" => new CURLFile('/Users/peter/Desktop/superneatimage.png'))
);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
print_r($response);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

Response as:

HTTP/1.1 400 Bad Request Server: Play Set-Cookie: lang=v=2&lang=en-us; Path=/; Domain=api.linkedin.com Date: Wed, 10 Apr 2019 09:16:25 GMT Content-Length: 0 X-Li-Fabric: prod-lsg1 Connection: keep-alive

Link to the Linkedin doc

Similar question from SO, which do not solved my issue.


Solution

  • Use Guzzle HTTP client instead of curl.I tried curl but it is not working.

    First install the composer in the current directory with below command:

    php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    php -r "if (hash_file('sha384', 'composer-setup.php') === '48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
    php composer-setup.php
    php -r "unlink('composer-setup.php');"
    

    After the composer Update, run below command to install the Guzzle (default version will be 3.9 it requires php >= 5.3.3.You can specify based on your php version):

    php composer.phar require guzzlehttp/guzzle

    Once Guzzle client installed successfully.Please use the below code to upload the file

        require 'vendor/autoload.php';
        $client =new \GuzzleHttp\Client();
        $image_path='/path_to_your_image/my_image.png';
        $result=$client->request('PUT',$target_url, [
                 'headers' => [
                     'Authorization' => 'Bearer ' . $token
                  ],
                  'body' => fopen($image_path, 'r'),
        
            ]);
    

    You will get below success full response

    HTTP/2 201

    date: Wed Apr 10 09:14:44 UTC 2019 server: Play set-cookie: lang=v=2&lang=en-us; Path=/; Domain=api.linkedin.com x-ambry-creation-time: Wed Apr 10 09:14:44 UTC 2019 access-control-allow-origin: https://www.linkedin.com content-length: 0

    Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and trivial to integrate with web services.

    • Simple interface for building query strings, POST requests, streaming large uploads, streaming large downloads, using HTTP cookies, uploading JSON data, etc...
    • Can send both synchronous and asynchronous requests using the same interface. Uses PSR-7 interfaces for requests, responses, and streams. This allows you to utilize other PSR-7 compatible libraries with Guzzle.
    • Abstracts away the underlying HTTP transport, allowing you to write environment and transport agnostic code; i.e., no hard dependency on cURL, PHP streams, sockets, or non-blocking event loops.
    • Middleware system allows you to augment and compose client behavior.