Uploading Multi-part files in julia

I am trying to upload an image to Slack using their API.

I have successfully uploaded some text message using the following function :

function send_message(msg::T, channel_id::T, token::T) where T<:AbstractString
    msg = Dict("channel"=>channel_id, "text"=>"$(msg)")
    msg_payload = JSON.json(msg)
    token = "Bearer " * token
    params = ["Content-Type" => "application/json; charset=utf-8", "Authorization" => token]
    url = "https://slack.com/api/chat.postMessage"

    r = HTTP.request("POST", url, params, msg_payload)
    return r

But I am failing to do the same for files, I have to do something with HTTP.form or HTTP.multipart but I could not find those documentation.

Here is the code snippet I am trying to upload a file :

channel_id = "C01HJGL1MTK"
auth_key = "xoxb-1590094798692-1596646938673-3PC9eIaEa8ojPiEuzL6nJBM6"
key = "Bearer "*auth_key
url = "https://slack.com/api/files.upload"

file = open("tmp/plot2.jpg", "r")
part_file = HTTP.Form(Dict("file"=>file))
params = ["Content-Type" => "multipart/form-data", "Authorization" => key]
payload = HTTP.Form(Dict("channel"=>channel_id, "file"=>file))  
# Error in the above line, but I am getting a workaround 

HTTP.request("POST", url, params, payload)

Provided the channel key and bearer token if anyone wanted to reproduce.

hey, did you solve this? thanks

I haven’t got a pure julia solution yet. I am just calling up python to deal with it until I find one.

I tried to improve the docs for HTTP.Form and HTTP.Multipart here: HTTP.jl#676

I believe (part of) the problem is that your Content-Type header does not include the multipart boundary. Fortunately HTTP.jl should add that automatically if your body is HTTP.Form.

This should probably work, but I have not tested with the Slack API:

headers = ["Authorization" => "Bearer *****"]
data = ["channel" => "*****", "file" => open("tmp/plot2.jpg", "r")]
body = HTTP.Form(data)
HTTP.post(url, headers, body)
1 Like

This really helped me. Thank you!!! Can we add some examples of uploading files in doc??

that’s clearly the proper solution. I am just calling the file upload API via curl and that also works for me (not sure that is what you are after…):

Base.run(`curl -F file=@$(fname) -F "initial_comment=say what" -F channels=xxxxxxxxx -H "Authorization: Bearer $(ENV["SLACK_FILES"])" https://slack.com/api/files.upload`)