0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

files.upload API 廃止におけるGASの改修

Last updated at Posted at 2024-08-22

きっかけ

最近Slackで新しいアプリを作ってテストしていたところ
Slack APIのfiles.uploadエンドポイントで以下のエラーが返却されうまくいきませんでした。

{'ok': False, 'error': 'method_deprecated'}

原因がさっぱりわからなくてググってみたところ以下の記事を偶然見かけました。

特に重要だったのが以下の内容です。
image.png
昔作ったアプリでは動作していたので変だなと思っていたら
この条件に該当していたことが判明しました。

詳細

SDKが提供されているプラットフォームであれば既存メソッド名にv2を付与すれば利用できるようですが
GASではスクラッチで実装しているのでこの方法は不可能でした。
以下の手順を踏む必要がありました。

image.png

最初にファイルアップロード専用のURLを取得してそこにファイル実体をアップロードし処理のクロージング通知をしてあげる必要があるみたいです。
以下の関数では一つのファイルをアップロードしてSlackに投稿するサンプル関数です。(ほぼChatGPT作)

/**
 * Slackにファイルをアップロードする関数
 * @param {string} name - ファイル名
 * @param {Blob} fileBlob - アップロードするファイルのBlob
 * @param {string} token - SlackのAPIトークン
 * @param {string} channel - ファイルを投稿するチャンネルID
 */
function uploadFileToSlack(name, fileBlob, token, channel) {
  // 1. ファイルのサイズを取得
  var fileSize = fileBlob.getBytes().length;

  // 2. files.getUploadURLExternal APIを呼び出してURLとファイルIDを取得
  var uploadUrlResponse = UrlFetchApp.fetch(`https://slack.com/api/files.getUploadURLExternal?filename=${name}&length=${fileSize}`, {
    method: "get",
    headers: {
      "Authorization": "Bearer " + token,
    }
  });
  
  var uploadUrlJson = JSON.parse(uploadUrlResponse.getContentText());
  if (!uploadUrlJson.ok) {
    throw new Error("Failed to get upload URL: " + uploadUrlJson.error);
  }
  
  var uploadUrl = uploadUrlJson.upload_url;
  var fileId = uploadUrlJson.file_id;

  console.log(uploadUrl)
  console.log(fileId)

  // 3. 取得したURLにファイルをアップロード
  var uploadResponse = UrlFetchApp.fetch(uploadUrl, {
    method: "post",
    payload: {
      token: token,
      file: fileBlob,
      filename: name
    }
  });

  if (uploadResponse.getResponseCode() !== 200) {
    throw new Error("Failed to upload file: " + uploadResponse.getContentText());
  }

  // 4. files.completeUploadExternal APIにファイルIDとオプション引数を送信してアップロードを完了
  var completeUploadPayload = {
    files: [{ id: fileId, title: name }]
  };

  if (channel) {
    completeUploadPayload.channel_id = channel;
  }

  var completeUploadResponse = UrlFetchApp.fetch("https://slack.com/api/files.completeUploadExternal", {
    method: "post",
    headers: {
      "Authorization": "Bearer " + token,
      "Content-Type": "application/json"
    },
    payload: JSON.stringify(completeUploadPayload)
  });

  var completeUploadJson = JSON.parse(completeUploadResponse.getContentText());
  if (!completeUploadJson.ok) {
    throw new Error("Failed to complete upload: " + completeUploadJson.error);
  }

  console.log(completeUploadJson);
  return completeUploadJson;
}

files.completeUploadExternalにはさらにinitial_commentやthread_tsといったパラメータもありますのでアップロードファイルにメッセージを付与したりスレッド内に投稿したりするこも可能です。
サンプルソースですと以下のような感じでパラメータを拡張してあげます。

completeUploadPayload.channel_id = channel;

ちなみに旧バージョンの関数はこちらです。

/**
 * Slackにファイルをアップロードする関数
 * @param {string} name - ファイル名
 * @param {Blob} fileBlob - アップロードするファイルのBlob
 * @param {string} token - SlackのAPIトークン
 * @param {string} channel - ファイルを投稿するチャンネルID
 */
function uploadFileToSlack(name, fileBlob, token, channel) {

  var url = 'https://slack.com/api/files.upload';
  var form = {
   token: token,
   title: name,
   filename: "filename",
   filetype: "auto",
   channels: channel,
   file: fileBlob
  };

  var options = {
    method: 'post',
    payload: form,
  };

  UrlFetchApp.fetch(url, options);
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?