Reputation: 123
Since the slack file.upload is going to be depreciated, I was going to make new the methods work.
The first one works as:
curl -s -F [email protected] -F filename=test.txt -F token=xoxp-token -F length=50123 https://slack.com/api/files.getUploadURLExternal
and returns
{"ok":true,"upload_url":"https:\/\/files.slack.com\/upload\/v1\/CwABAAAAXAoAAVnX....","file_id":"F07XXQ9XXXX"}
The second request is:
curl -X POST \ -H "Authorization: Bearer xoxp-token" \
-H "Content-Type: application/json" \
-d '{
"files": [{"id":"F07XXXXXX", "title":"Slack API updates Testing"}],
"channel_id": "C06EXXXXX"
}' \
https://slack.com/api/files.completeUploadExternal
With the second request, I get 200 OK responses.
{"ok":true,"files":[{"id":"XXXXXXX","created":XXXXXXXX,"timestamp":XXXXXXXX,"name":"test.txt","title":"Slack API updates Testing","mimetype":"","filetype":"","pretty_type":"","user":"XXXXXXXXX","user_team":"XXXXXXXXX","editable":false,"size":50123,"mode":"hosted","is_external":false,"external_type":"","is_public":false,"public_url_shared":false,"display_as_bot":false,"username":"","url_private":"https:\/\/files.slack.com\/files-pri\/XXXXXXXXX-XXXXXXX\/test.txt","url_private_download":"https:\/\/files.slack.com\/files-pri\/XXXXXXXXX-XXXXXXX\/download\/test.txt","media_display_type":"unknown","permalink":"https:\/\/XXXXXXXX.slack.com\/files\/XXXXXXXXX\/XXXXXXX\/test.txt","permalink_public":"https:\/\/slack-files.com\/XXXXXXXXX-XXXXXXX-XXXXXXXX","comments_count":0,"is_starred":false,"shares":{},"channels":[],"groups":[],"ims":[],"has_more_shares":false,"has_rich_preview":false,"file_access":"visible"}],"warning":"missing_charset","response_metadata":{"warnings":["missing_charset"]}}
Questions and problems: 1- How do I determine the length= in the first request (files.getUploadURLExternal ) 2- Even though I have provided the channel_id the file is still not getting uploaded on the Slack channel.
Documentation: https://api.slack.com/methods/files.completeUploadExternal https://api.slack.com/methods/files.getUploadURLExternal
Upvotes: 5
Views: 4346
Reputation: 11
I believe slack's official documentation is wrong. El David's answer is working for me, slack suggests using PUT but it doesn't work. Using POST is solved it basically.
Upvotes: 0
Reputation: 41
Python implementation below, assuming a filestream input. I was getting the 'internal error: put' as well during the 2nd step, ended up being a malformed request
from io import BytesIO
import requests
SLACK_TOKEN = 'xxxxxxxxx'
SLACK_ENDPOINT = "https://slack.com/api/"
file_stream = BytesIO()
file_stream.write("Test text.".encode('utf-8'))
filename = 'arg.txt'
file_stream.seek(0, 2) # Move to end of file
length = file_stream.tell()
file_stream.seek(0) # Reset to start of file
# Get an upload URL
upload_url_resp = requests.post(
url=f"{SLACK_ENDPOINT}files.getUploadURLExternal",
headers={"Authorization": f"Bearer {SLACK_TOKEN}"},
data={"filename": filename, "length": length}
)
upload_url_data = upload_url_resp.json()
if (upload_url := upload_url_data.get('upload_url')) and (file_id := upload_url_data.get('file_id')):
# Upload the file to the returned URL
up_resp = requests.post(
upload_url,
files={'file': (filename, file_stream)},
json={'filename': filename}
)
resp = requests.post(
url=f"{SLACK_ENDPOINT}files.completeUploadExternal",
headers={"Authorization": f"Bearer {SLACK_TOKEN}"},
json={
"files": [{'id': file_id, 'title': filename}],
"channel_id": 'tgt_channel_id',
"initial_comment": "Testing File Upload",
}
)
Upvotes: 1
Reputation: 696
This is the complete bash script to upload any file using the slack API. Stage 4 is optional, only for personal token.
#!/bin/bash
export FILE_PATH="/folder/your.file"
export CHANNEL_ID="C_some_number"
export TOKEN="your_token"
FILENAME=$(basename "$FILE_PATH")
# Get the file size using macOS compatible stat command. use stat -c%s "$FILE_PATH" otherwise
FILE_SIZE=$(stat -f%z "$FILE_PATH")
# Stage 1: Get an upload URL
UPLOAD_URL_RESPONSE=$(curl -s -F files=@"$FILENAME" -F filename="$FILENAME" -F token=$TOKEN -F length=$FILE_SIZE https://slack.com/api/files.getUploadURLExternal)
UPLOAD_URL=$(echo "$UPLOAD_URL_RESPONSE" | jq -r '.upload_url')
FILE_ID=$(echo "$UPLOAD_URL_RESPONSE" | jq -r '.file_id')
if [ "$UPLOAD_URL" == "null" ]; then
echo "Error getting upload URL: $UPLOAD_URL_RESPONSE"
exit 1
fi
# Stage 2: Upload the file to the provided URL
UPLOAD_RESPONSE=$(curl -s -X POST \
-T "$FILE_PATH" \
-H "Content-Type: application/octet-stream" \
"$UPLOAD_URL")
if [ $? -ne 0 ]; then
echo "Error uploading file: $UPLOAD_RESPONSE"
exit 1
fi
# Stage 3: Complete the upload, and post the message and the file
COMPLETE_RESPONSE=$(curl -s -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json;charset=utf-8" \
-d '{
"files": [
{
"id": "'"$FILE_ID"'"
}
],
"channel_id": "'"$CHANNEL_ID"'",
"initial_comment": "Hello file 001"
}' \
https://slack.com/api/files.completeUploadExternal)
if [ "$(echo "$COMPLETE_RESPONSE" | jq -r '.ok')" != "true" ]; then
echo "Error completing upload: $COMPLETE_RESPONSE"
exit 1
fi
# OPTIONAL Stage 4: Share the uploaded file in a channel, only if it was not performed in the previous stage
SHARE_RESPONSE=$(curl -s -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json;charset=utf-8" \
-d '{
"channel": "'"$CHANNEL_ID"'",
"file": "'"$FILE_ID"'",
"initial_comment": "Hello file 002"
}' \
https://slack.com/api/files.sharedPublicURL)
if [ "$(echo "$SHARE_RESPONSE" | jq -r '.ok')" != "true" ]; then
echo "Error sharing file: $SHARE_RESPONSE"
exit 1
fi
echo "File successfully uploaded. Is not then check your token scopes"
Upvotes: 7
Reputation: 11
Im doing the same with my bot but in the step 2 when you have to upload the file, im getting an error "internal error: put".
upload_file = HTTP::Client.post(upload_url, headers, body: file_basename) //tried using file_basename and file_path
This is the answer to upload_file
#<HTTP::Client::Response:0x7f923f16caf0 @version="HTTP/1.1", @status=INTERNAL_SERVER_ERROR, @status_message="Internal Server Error", @headers=HTTP::Headers{"Content-Type" => "text/plain", "Content-Length" => "19", "Connection" => "close", "x-backend" => "miata-prod-gru-v2-5bcfb8465b-pt2fj", "date" => "Wed, 29 May 2024 19:06:28 GMT", "x-envoy-upstream-service-time" => "2", "x-edge-backend" => "miata", "x-slack-edge-shared-secret-outcome" => "shared-secret", "server" => "envoy", "via" => "envoy-edge-gru-cseuczvq, 1.1 5ea4a2b9e3595a42471d782e7c7054d0.cloudfront.net (CloudFront)", "X-Cache" => "Error from cloudfront", "X-Amz-Cf-Pop" => "EZE50-P1", "X-Amz-Cf-Id" => "LfAqYrT_5Pc-XdooQfTjR9U2cH4uxabEx-5Yki8r5qVKPSRVY-2UQw==", "Cross-Origin-Resource-Policy" => "cross-origin"}, @body_io=nil, @cookies=nil, @body="internal error: put">
Upvotes: 1
Reputation: 16
You skipped a step. You have to send a POST to the URL that is returned to you on the first step. In that post you are also doing the file upload.
2nd step should be:
curl -F filename="@$filename" -H "Authorization: Bearer $SLACK_KEY" -v POST $upload_url
then your 2nd step should be the 3rd step.
As far as getting the byte size stat --printf="%s" file
if you are using bash
Upvotes: 0