programming

Slack files.upload 웹 API 메소드 변경 사항 처리하기


by Kitle · 2025. 04. 21.




Slack files.upload 웹 API 메소드 변경 사항 처리하기

안녕하세요.

예정된 날짜 및 봇 앱에 영향을 미치는 files.upload 웹 API 메소드 변경 사항에 대해 다시 알려드리고자 합니다.

files.upload API에 대한 지원이 중단될 예정입니다.

이 변경 사항을 대비하기 위해 files.upload에서 마이그레이션하는 대신 files.getUploadURLExternal과 files.completeUploadExternal을 조합하여 사용하는 것이 좋습니다. 이 두 API를 함께 사용하는 방법에 대한 자세한 내용은 파일 작업 문서에서 확인할 수 있습니다. 또한 api.slack 페이지에서 Slack의 SDK를 활용하여 이 새로운 파일 업로드 방식으로의 전환을 지원할 수도 있습니다.

해결 방법

기존 해결 방법 https://slack.com/api/files.upload post 로 한번에 쏘던것을 다음과 같이 3단계로 나누어 해야함


새로운 처리 방법

1) https://slack.com/api/files.getUploadURLExternal post 요청으로 upload_url, file_id 응답 받기

2) upload_url 로 post 요청으로 파일 업로드 하기

3) https://slack.com/api/files.completeUploadExternal post로 요청보내서 슬랙에 파일 보여주기

def get_upload_url(title):
    url = "https://slack.com/api/files.getUploadURLExternal"

    headers = {"Authorization": f"Bearer {token}"}

    with open(f"{title}.png", "rb") as f:
        file_length = len(f.read())

    data = {"filename": f"{title}.png", "length": str(file_length)}

    response = requests.post(url, headers=headers, data=data)

    response_data = response.json()

    if not response_data.get("ok"):
        raise Exception(f"Error getting upload URL: {response_data}")
    return response_data["upload_url"], response_data["file_id"]


def upload_file(upload_url, title):
    with open(f"{title}.png", "rb") as file_data:
        response = requests.post(url=upload_url, data=file_data)

    if response.status_code != 200:
        raise Exception(f"Error uploading file: {response.text}")

def complete_upload(file_id, title, channel_id, thread_ts):
    file_header = { "Content-Type": "application/json; charset=utf-8",
                   'Authorization': f'Bearer {token}'}
    upload_url = 'https://slack.com/api/files.completeUploadExternal'
    data = {"files": [{"id": file_id, "title": title}],
            "channel_id": channel_id,
            "thread_ts": thread_ts,
            }
    try:
        requests.post(url=upload_url, headers=file_header, json=data)
    except Exception as e :
        print(e)

upload_url, file_id = get_upload_url(title)
upload_file(upload_url, title)
complete_upload(file_id, title, channel_id, thread_ts)


직접 올리지 않고 Blocks 내에서 보내는 경우 

바로 슬랙에 파일 업로드 하는 케이스는 위와 같이 처리하면 되고,  /command 등 스샷 이미지를 blocks 에서 보내는 경우는 아래와 같이 처리하여 해결한다.

상단의 

1 get_upload_url ,

2 upload_file 은 동일하고

3 complete_upload 시에는 채널명은 옵셔널이라 지정하지 않고 업로드 가능하다.


메세지를 post 할때 필요한 것은 업로드 완료 후 response의 url_private 를 리턴해둔다.

def complete_upload(file_id, filename):
    uploaded_permalink = None
    file_header = { "Content-Type": "application/json; charset=utf-8",
                   'Authorization': f'Bearer {slack_token}'}
    upload_url = 'https://slack.com/api/files.completeUploadExternal'
    data = {"files": [{"id": file_id, "title": f"{filename}"}],
            }
    try:
        response = requests.post(url=upload_url, headers=file_header, json=data)
        response_data = response.json()
        uploaded_permalink = response_data["files"][0]["url_private"]
    except Exception as e :
        print(e)
    return uploaded_permalink

4 data의 block 안에 type, image url 을 위에서 받은 링크로 넣고 alt_text 추가 하고 전송함

data = {
        "token": slack_token,
        "channel": value_channel_label,
        "blocks": [
            {
                "type": "image",
                "image_url": uploaded_permalink,
                "alt_text": "Uploaded Image"
            }
        ]

try:
    # 너무 빠르면 참조 에러남 3초 슬립 넣음 왜그런지 원인불명
    sleep(3)
    requests.post("https://slack.com/api/chat.postMessage", headers=headers, data=json.dumps(data))
except Exception as e:
    print(e)

주의사항

99%는  'response_metadata': {'messages': ['[ERROR] invalid slack file [json-pointer:/blocks/0/slack_file]'] 에러가 발생함.


해결은 되었으나 구글링도 답도없고 아주 간헐적으로 될때도 있어서  그냥 sleep(3)을 임시로 넣어서 해결. 뭔가 더 깔끔한 방법이 있을것 같으나 찾지 못한 상태이다.