How to upload files to slack using file.upload and requests

Question:

I’ve been searching a lot and I haven’t found an answer to what I’m looking for.

I’m trying to upload a file from /tmp to slack using python requests but I keep getting {"ok":false,"error":"no_file_data"} returned.

file={'file':('/tmp/myfile.pdf', open('/tmp/myfile.pdf', 'rb'), 'pdf')}
payload={
        "filename":"myfile.pdf", 
        "token":token, 
        "channels":['#random'], 
        "media":file
        }

r=requests.post("https://slack.com/api/files.upload", params=payload)

Mostly trying to follow the advice posted here

Asked By: arshbot

||

Answers:

Sending files through http requires a bit more extra work than sending other data. You have to set content type and fetch the file and all that, so you can’t just include it in the payload parameter in requests.

You have to give your file information to the files parameter of the .post method so that it can add all the file transfer information to the request.

my_file = {
  'file' : ('/tmp/myfile.pdf', open('/tmp/myfile.pdf', 'rb'), 'pdf')
}

payload={
  "filename":"myfile.pdf", 
  "token":token, 
  "channels":['#random'], 
}

r = requests.post("https://slack.com/api/files.upload", params=payload, files=my_file)
Answered By: Caleb Lewis

Base on the Slack API file.upload documentation
What you need to have are:

  • Token : Authentication token bearing required scopes.
  • Channel ID : Channel to upload the file
  • File : File to upload

Here is the sample code. I am using WebClient method in @slack/web-api package to upload it in slack channel.

import { createReadStream } from 'fs';
import { WebClient } from '@slack/web-api';

const token = 'token'
const channelId = 'channelID'
const web = new WebClient(token);

const uploadFileToSlack = async () => {
   await web.files.upload({
     filename: 'fileName',
     file: createReadStream('path/file'),
     channels: channelId,
   });
}
Answered By: Richard Vergis

Writing this post, to potentially save you all the time I’ve wasted. I did try to create a new file and upload it to Slack, without actually creating a file (just having it’s content). Because of various and not on point errors from the Slack API I wasted few hours to find out that in the end, I had good code from the beginning and simply missed a bot in the channel.

This code can be used also to open an existing file, get it’s content, modify and upload it to Slack.

Code:

from io import StringIO # this library will allow us to 
# get a csv content, without actually creating a file.

sio = StringIO()
df.to_csv(sio) # save dataframe to CSV
csv_content = sio.getvalue()
filename = 'some_data.csv'

token=os.environ.get("SLACK_BOT_TOKEN")
url = "https://slack.com/api/files.upload"
request_data = {
    'channels': 'C123456', # somehow required if you want to share the file 
# it will still be uploaded to the Slack servers and you will get the link back
    'content': csv_content, # required
    'filename': filename, # required
    'filetype': 'csv', # helpful :)
    'initial_comment': comment, # optional
    'text': 'File uploaded', # optional
    'title': filename, # optional
    #'token': token, # Don't bother - it won't work. Send a header instead (example below).
}
headers = {
    'Authorization': f"Bearer {token}",
}
response = requests.post(
    url, data=request_data, headers=headers
)

OFFTOPIC – about the docs

I just had a worst experience (probably of this year) with Slack’s file.upload documentation. I think that might be useful for you in the future.

Things that were not working in the docs:

  1. token – it cannot be a param of the post request, it must be a header. This was said in one of github bug reports by actual Slack employee.
  2. channel_not_found – I did provide an existing, correct channel ID and got this message. This is somehow OK, because of security reasons (obfuscation), but why there is this error message then: not_in_channelAuthenticated user is not in the channel. After adding bot to the channel everything worked.
  3. Lack of examples for using content param (that’s why I am sharing my code with you.
  4. Different codding resulted with different errors regarding form data and no info in the docs helped to understand what might be wrong, what encoding is required in which upload types.

The main issue is they do not version their API, change it and do not update docs, so many statements in the docs are false/outdated.

Answered By: Mr.TK