Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot upload file to Channel using Api #1575

Open
nobikin95 opened this issue Oct 25, 2024 · 6 comments
Open

Cannot upload file to Channel using Api #1575

nobikin95 opened this issue Oct 25, 2024 · 6 comments
Labels
question M-T: User needs support to use the project Version: 3x web-client

Comments

@nobikin95
Copy link

I am trying to upload a file to a private Slack channel using the Slack API via the following Python script.
However, once uploaded, the file cannot be downloaded by users in the channel. I am looking for help to understand why this is happening and how to resolve it.

Python runtime version

3.12.1

I used these step:

  1. https://slack.com/api/files.getUploadURLExternal
  2. https://slack.com/api/files.completeUploadExternal
  3. https://slack.com/api/files.sharedPublicURL

Actual result:

{
  "ok": true,
  "file": {
    "id": "XXXXXXXXXX",
    "created": 1729848820,
    "timestamp": 1729848820,
    "name": "xxxxxxxxxxxxxxxxxx.xxx",
    "title": "xxxxxxxxxxxxxxxxxxxx.xxx",
    "mimetype": "",
    "filetype": "",
    "pretty_type": "",
    "user": "XXXXXXXXX",
    "user_team": "XXXXXXXX",
    "editable": false,
    "size": 61652577,
    "mode": "hosted",
    "is_external": false,
    "external_type": "",
    "is_public": false,
    "public_url_shared": true,
    "display_as_bot": false,
    "username": "",
    "url_private": "https://files.slack.com/files-pri/xxxxxxxxx-xxxxxxxxxx/xxxxxxxxxxxxxxxxxx.xxx",
    "url_private_download": "https://files.slack.com/files-pri/xxxxxxxxxxxxx-xxxxxxx/download/xxxxxxxxxxxxxxxxxx.xxx",
    "media_display_type": "unknown",
    "permalink": "https://xxxxxxxxx.slack.com/files/xxxxxxxxxx/xxxxxxxxxxxxxxx/xxxxxxxxxxxxx.xxx",
    "permalink_public": "https://slack-files.com/xxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxxxxx",
    "comments_count": 0,
    "is_starred": false,
    "shares": {},
    "channels": [],
    "groups": [],
    "ims": [],
    "has_more_shares": false,
    "has_rich_preview": false,
    "file_access": "visible"
  }
}
@srajiang
Copy link
Contributor

Hi @nobikin95 - I noticed that the successful output has is_public: false, and the channels array is empty. What was your output for the files.completeUploadExternal request? I just want to check here that you supplied the channel_id, otherwise the file will be private.

@srajiang srajiang added question M-T: User needs support to use the project and removed untriaged labels Oct 25, 2024
@nobikin95
Copy link
Author

Hi @srajiang, output for the files.completeUploadExternal :

  "ok": true,
  "files": [
    {
      "id": "xxxxxxx",
      "created": 1729847794,
      "timestamp": 1729847794,
      "name": "xxxxxxxxxxxxx.xxx",
      "title": "xxxxxxxxxxx.xxx",
      "mimetype": "",
      "filetype": "",
      "pretty_type": "",
      "user": "xxxxxxxxx",
      "user_team": "xxxxxxxxx",
      "editable": false,
      "size": 61652512,
      "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/XXXXXXXXXXXXX-XXXXXXXXXXX/xxxxxxxxxxxxxxxxx.xxx",
      "url_private_download": "https://files.slack.com/files-pri/XXXXXXXXXXXXX-XXXXXXXXXXX/download/xxxxxxxxxxxxxxxxx.xxx",
      "media_display_type": "unknown",
      "permalink": "https://ikameglobal.slack.com/files/XXXXXXXXXXXXX/XXXXXXXXXXXXX/xxxxxxxxxxxxxxxxx.xxx",
      "permalink_public": "https://slack-files.com/XXXXXXXXXXXXX-XXXXXXXXXXXXX-xxxxxxxxxx",
      "comments_count": 0,
      "is_starred": false,
      "shares": {},
      "channels": [],
      "groups": [],
      "ims": [],
      "has_more_shares": false,
      "has_rich_preview": false,
      "file_access": "visible"
    }
  ]
}

@nobikin95
Copy link
Author

nobikin95 commented Oct 28, 2024

It seems like I'm having an issue with channel_id, here is the code I'm using:

#!/bin/bash

FILE_PATH=$1
CHANNEL_ID="XXXXXXXXXXX"
USER_TOKEN="xoxp-"  
BOT_TOKEN="xoxb-"   

# Check if the file exists
echo "Checking if file exists at: $FILE_PATH"
if [ ! -f "$FILE_PATH" ]; then
    echo "Error: File $FILE_PATH does not exist!"
    exit 1
fi
echo "File found at: $FILE_PATH"

# Get file size (use command compatible with macOS and Linux)
if [[ "$OSTYPE" == "darwin"* ]]; then
    FILE_SIZE=$(stat -f%z "$FILE_PATH")
else
    FILE_SIZE=$(stat -c%s "$FILE_PATH")
fi

# Step 1: Get upload URL using the files.getUploadURLExternal API
echo "Fetching upload URL from Slack API..."
UPLOAD_URL_RESPONSE=$(curl -s -X POST \
    -H "Authorization: Bearer $USER_TOKEN" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    --data "filename=$(basename "$FILE_PATH")&length=$FILE_SIZE&channels=$CHANNEL_ID" \
    https://slack.com/api/files.getUploadURLExternal)

# Log the response from the API
echo "Response from files.getUploadURLExternal: $UPLOAD_URL_RESPONSE"

# Extract upload URL and file_id from JSON response
UPLOAD_URL=$(echo "$UPLOAD_URL_RESPONSE" | grep -o '"upload_url":"[^"]*' | sed 's/"upload_url":"//g' | sed 's/\\//g')
FILE_ID=$(echo "$UPLOAD_URL_RESPONSE" | grep -o '"file_id":"[^"]*' | sed 's/"file_id":"//g')

# Check if the URL or file_id was not obtained
if [ -z "$UPLOAD_URL" ] || [ -z "$FILE_ID" ]; then
    echo "Error: Failed to get upload URL or file_id"
    exit 1
fi
echo "Upload URL: $UPLOAD_URL"
echo "File ID: $FILE_ID"

# Step 2: Upload the file to the obtained URL
echo "Uploading file to: $UPLOAD_URL"
UPLOAD_RESULT=$(curl -s -X PUT \
    -H "Content-Type: application/octet-stream" \
    --data-binary @"$FILE_PATH" \
    "$UPLOAD_URL")

# Log the upload result
echo "Result of file upload: $UPLOAD_RESULT"

# Step 3: Complete the upload using the files.completeUploadExternal API
echo "Completing file upload with Slack API..."
COMPLETE_RESPONSE=$(curl -s -X POST \
    -H "Authorization: Bearer $USER_TOKEN" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    --data-urlencode "files=[{\"id\":\"$FILE_ID\"}]" \
    --data-urlencode "channels=$CHANNEL_ID" \
    https://slack.com/api/files.completeUploadExternal)

# Log the response from the files.completeUploadExternal API
echo "Response from files.completeUploadExternal: $COMPLETE_RESPONSE"

# Step 3.1: Share the public URL using the files.sharedPublicURL API
echo "Sharing file publicly using Slack API..."
SHARED_PUBLIC_URL_RESPONSE=$(curl -s -X POST \
    -H "Authorization: Bearer $USER_TOKEN" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    --data "file=$FILE_ID" \
    https://slack.com/api/files.sharedPublicURL)

# Log the response from the files.sharedPublicURL API
echo "Response from files.sharedPublicURL: $SHARED_PUBLIC_URL_RESPONSE"

# Extract URL from JSON response (use permalink instead of permalink_public)
PUBLIC_URL=$(echo "$SHARED_PUBLIC_URL_RESPONSE" | grep -o '"permalink_public":"[^"]*' | sed 's/"permalink_public":"//g' | sed 's/\\//g')

# Check if the URL was not obtained
if [ -z "$PUBLIC_URL" ]; then
    echo "Error: Failed to get permalink URL"
    exit 1
fi
echo "Public URL: $PUBLIC_URL"

# Step 4: Post a message to the channel with the uploaded file using chat.postMessage API
echo "Posting message to channel with uploaded file ..."
POST_MESSAGE_RESPONSE=$(curl -s -X POST \
    -H "Authorization: Bearer $USER_TOKEN" \
    -H "Content-Type: application/json" \
    --data "$(cat <<EOF
{
    "channel": "$CHANNEL_ID",
    "text": "Build Success: <$PUBLIC_URL>",
    "attachments": [
        {
            "title": "Click here to download",
            "title_link": "$PUBLIC_URL",
            "text": "The file is available for public download."
        }
    ]
}
EOF
    )" \
    https://slack.com/api/chat.postMessage)

# Log the response from the chat.postMessage API
echo "Response from chat.postMessage: $POST_MESSAGE_RESPONSE"

@seratch
Copy link
Member

seratch commented Oct 28, 2024

The cause of your confusion may not be related to this, but the files.completeUploadExternal API processes its tasks asynchronously. This means that if a subsequent operation attempts to download the uploaded file immediately, it might fail until the files.completeUploadExternal operation completes. It appears that your code is trying to download the files right away. In most cases, this can fail regardless of whether the files are public or private.

One way to determine if the upload operation is finished is to check if the "shares" property is available in the file's metadata. You can verify this by polling the files.info API with the uploaded file's ID.

Copy link

github-actions bot commented Dec 2, 2024

👋 It looks like this issue has been open for 30 days with no activity. We'll mark this as stale for now, and wait 10 days for an update or for further comment before closing this issue out. If you think this issue needs to be prioritized, please comment to get the thread going again! Maintainers also review issues marked as stale on a regular basis and comment or adjust status if the issue needs to be reprioritized.

@honungsburk
Copy link

I've been stumped by this api. My file gets uploaded and I've set the channel_id but it still is not seeing it in the channel. From the documentation it seems like the file should show up in the channel but perhaps that is not the case?

calling files.completeUploadExternal (I'm using Elixir) with this body:

%{
  files: [%{id: "xxxxxxxxx", title: "Galaxy Book Pro.pdf"}],
  thread_ts: "xxxxxxxx.xxxxxx",
  initial_comment: "Attachments",
  channel_id: "xxxxxxxxxx"
}

I get this response:

%{
  "files" => [
    %{
      "filetype" => "",
      "mode" => "hosted",
      "comments_count" => 0,
      "public_url_shared" => false,
      "file_access" => "visible",
      "is_starred" => false,
      "channels" => [],
      "url_private" => "https://files.slack.com/files-pri/xxxxxxxx-xxxxxxxx/galaxy_book_pro.pdf",
      "url_private_download" => "https://files.slack.com/files-pri/xxxxxxxx-xxxxxxxx/download/galaxy_book_pro.pdf",
      "created" => 1733998180,
      "media_display_type" => "unknown",
      "external_type" => "",
      "mimetype" => "",
      "has_rich_preview" => false,
      "pretty_type" => "",
      "ims" => [],
      "groups" => [],
      "shares" => %{},
      "name" => "Galaxy Book Pro.pdf",
      "id" => "xxxxxxxxxxx",
      "display_as_bot" => false,
      "user" => "xxxxxxxxxx",
      "size" => 45061,
      "has_more_shares" => false,
      "permalink_public" => "https://slack-files.com/xxxxxxxx-xxxxxxx-xxxxxxx",
      "timestamp" => 1733998180,
      "user_team" => "xxxxxxxxx",
      "permalink" => "https://upptec.slack.com/files/xxxxxxxx/xxxxxxxx/galaxy_book_pro.pdf",
      "title" => "Galaxy Book Pro.pdf",
      "is_external" => false,
      "username" => "",
      "editable" => false,
      "is_public" => false
    }
  ],
  "ok" => true
}

Using files.info I can find the file:

{
  "ok": true,
  "file": {
    "id": "xxxxxxxxxx",
    "created": 1733998180,
    "timestamp": 1733998180,
    "name": "Galaxy Book Pro.pdf",
    "title": "Galaxy Book Pro.pdf",
    "mimetype": "",
    "filetype": "",
    "pretty_type": "",
    "user": "xxxxxxxxxx",
    "user_team": "xxxxxxxx",
    "editable": false,
    "size": 45061,
    "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/xxxxxxx-xxxxxxx/galaxy_book_pro.pdf",
    "url_private_download": "https://files.slack.com/files-pri/xxxxxxxx-xxxxxxxx/download/galaxy_book_pro.pdf",
    "media_display_type": "unknown",
    "permalink": "https://X.slack.com/files/xxxxxxxxxx/xxxxxxxx/galaxy_book_pro.pdf",
    "permalink_public": "https://slack-files.com/xxxxxxxxx-xxxxxxxx-xxxxxx",
    "favorites": [],
    "is_starred": false,
    "shares": {},
    "channels": [],
    "groups": [],
    "ims": [],
    "has_more_shares": false,
    "has_rich_preview": false,
    "file_access": "visible",
    "comments_count": 0
  },
  "comments": [],
  "response_metadata": {
    "next_cursor": ""
  }
}

Note: I've redacted ids

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question M-T: User needs support to use the project Version: 3x web-client
Projects
None yet
Development

No branches or pull requests

4 participants