Mattermost, Inc.

API Docs: File Upload API

I’m having trouble determining the correct API endpoint and the correct API fields to use to upload a file to a channel.

I have seen issue #1693 on Github for a similar question and a few posts about it on here. The only answers provided are links to the Javascript and the Go driver. I tried reverse engineering those drivers to figure out what fields are required to do this to no avail.

I’ve also read in the documentation on the MM website that the new API Version is directly compatiable with the Slack API. I’ve tried to port this code over, no luck.

I think I am almost there. Could anyone give me a hand? I am using Python 2.x with the requests module.

import re
import requests
import json
from pprint import pprint

def authenticate():
    payload = { "name": "name", "login_id": "username", "password": "password" }
    headers = { "content-type": "application/json" }
    s = requests.Session()
    r = s.post("https://mmdomaingoeshere/api/v3/users/login", data=json.dumps(payload), headers=headers, verify=False)
    authToken = r.headers.get("Token")

    return authToken

def postFile(token, file_):
    headers = { "Authorization": "Bearer %s" % (token), "Accept": "application/json", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en" }

    files = {"file": open(file_, 'rb'), "filename": file_}
    data = {"channel_id": "45w79egbpfy4iq15ug7cn6ai8c"}

    r = requests.post("https://mmdomaingoeshere/api/v3/teams/f74asir3gbnyfjcysn1b36iube/files/upload", headers=headers, files=files, data=data, verify=False)
    pprint(r.json())

if __name__ == "__main__":
    token = authenticate()
    postFile(token, "testFile")

Here’s the output

{u'client_ids': [], u'filenames': []}

Hi @gleblanc1783,

Your code looks good, except you’ve got a small typo when preparing the file to attach to the request.

    files = {"file": open(file_, 'rb'), "filename": file_} # incorrect

This should have refer to the file you’re uploading as “files” since this API route can receive multiple files at once.

    files = {"files": open(file_, 'rb'), "filename": file_} # correct

You’ll then get back a filename that you can attach to a Post object when making sending a message.

Also, regarding the Slack compatibility, that’s only for our Webhooks and Slash commands. The REST api doesn’t try to be compatible with Slack.

Update: This uploads the file with an incorrect file name. See my more recent comment below for the correct call

1 Like

@hmhealey, I’m having some issues getting the filename to be posted along with the file. This is the response I get back after posting a file.

  {'client_ids': [], 
        'file_infos': [{'create_at': 1496944234739, 
            'delete_at': 0, 
            'extension': '', 
            'id': 'nymiczof6jrk5bmqyxu67tgdxe', 
            'mime_type': '', 
            'name': 'files', 
            'size': 1325259, 
            'update_at': 1496944234739, 
            'user_id': 'zsti4betdprx3f5jgmspxs38zc'}]} 

When I try to post the file in a channel it shows up with the name “files” instead of the filename. It seems like the filename isn’t making it to the server at all. Any ideas? This is the code I’m using to send my upload request.

    files = {
        'files': fileBytes,
        'filename': filePath
    }
    data = {
        'channel_id': channelId,
    }

    res = requests.post(
        self.server + url, 
        headers=headers, 
        data=data, 
        files=files, 
        verify=False
    )
    return res

@braddaniels It looks like you’re using the Python requests library, correct? I’m not 100% on the format they expect for files, but it looks like you should be using

files = {
    'files': ('file': (filePath, fileBytes)}
}

instead of having the filename as a separate entry in files.

http://docs.python-requests.org/en/master/user/quickstart/#post-a-multipart-encoded-file

Oh sorry, I didn’t realize I’m correcting my own example from before. I should re-read the rest of the thread next time instead of just skimming :stuck_out_tongue: