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)을 임시로 넣어서 해결. 뭔가 더 깔끔한 방법이 있을것 같으나 찾지 못한 상태이다.