Search code examples
phpslackslack-api

Upload a file to slack with files.upload in PHP


I'm trying to use the files.upload method to upload a file to Slack, but I only got a blank message so far.

This is the code, I found this script on the internet, but it's not working.

<?php
include '../connessione.php';

$slacktoken = "myToken"; //this is not the real token ofc
$header = array();
$header[] = 'Content-Type: multipart/form-data';
$file = new CurlFile('../tmp/slack_icon.png', 'image/png');

$postitems =  array(
    'token' => $slacktoken,
    'channels' => "test_channel",
    'file' =>  $file,
    'text' => "This is my photo",
    'title' => "Photo title",
    'filename' => "myIcon.jpg"
);

$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_URL, "https://slack.com/api/files.upload");
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS,$postitems);

//Execute curl and store in variable
$data = curl_exec($curl);
?>

What am I doing wrong?

Thank you.

Edit: after lots of tests I got this message if I echo the $data variable:

{"ok":false,"error":"missing_scope","needed":"files:write:user","provided":"identify,commands"}

UPDATE I'll post here the full working code.

<?php
include '../connessione.php';

    // Buffer all upcoming output...
    ob_start();

    // Send your response.
    echo "Here be response";

    // Get the size of the output.
    $size = ob_get_length();

    // Disable compression (in case content length is compressed).
    header("Content-Encoding: none");

    // Set the content length of the response.
    header("Content-Length: {$size}");

    // Close the connection.
    header("Connection: close");

    // Flush all output.
    ob_end_flush();
    ob_flush();
    flush();

    // Close current session (if it exists).
    if(session_id()) session_write_close();


$channel = $_POST['channel_id'];
$slacktoken = "myToken";
$header = array();
$header[] = 'Content-Type: multipart/form-data';
$file = new CurlFile('slack_icon.png', 'image/png');



$postitems =  array(
        'token' => $slacktoken,
        'channels' => "test_channel",
        'file' =>  $file,
        'text' => "This is my photo",
        'title' => "Photo title",
        'filename' => "myIcon.jpg"
    );

$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_URL, "https://slack.com/api/files.upload");
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postitems);

//Execute curl and store in variable
$data = curl_exec($curl);
?>

The initial part is taken from this continue processing php after sending http response. That's needed to send an immediate answer back to Slack and avoid the "Timeout was reached" message.


Solution

  • Missing scopes

    You token is missing the necessary scopes, here: files:write:user.

    To add additional scopes:

    Assuming you have a Slack app, go to the management page for your app and then add it on the "Ouath" sub page there is a scope section where you can add it. here is a direct link to your apps: https://api.slack.com/apps.

    After that you need to re-install your app to the workspace, so the changes become active.

    Working with CurlFile

    Another potential pitfall is that CurlFile apparently only works with absolute paths to your file. (see this answer). A quick fix would be something like this:

    $file = new CurlFile(realpath(dirname(__FILE__) . '/../tmp/slack_icon.png'), 'image/png');