質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.12%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

受付中

LINE広告APIをGASを使い画像データ(ドライブにあるデータ)をPOSTしたい。

Asxce
Asxce

総合スコア1

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0回答

0グッド

0クリップ

150閲覧

投稿2022/10/02 04:15

実現したいこと

LINE広告APIをGASを使い画像データ(ドライブにあるデータ)をPOSTしたい。
詳細
ドライブに保存してあるGASという名前のフォルダーからtest.jpegという名前の画像データを名前経由で取得し、そのデータを使ってLINE広告APIの
Media/uploadをしたい。
ドキュメント
https://ads.line.me/public-docs/v3/3.9.1/certificated-ad-tech-general-partner#_updatecampaign

発生している問題・エラーメッセージ

Exception: Request failed for https://ads.line.me returned code 400. Truncated server response: {"errors":[{"reason":"DECODING_FAILED","message":"failed to decode input stream"}]}

decodeしてくれない。。

該当のソースコード

gas

1function adMedia() { 2 const today = new Date(); 3 const accountId = "xxxxxxxx"; 4 const access_key = "xxxxxxxxx"; 5 const secret_key = "xxxxxxxxx"; 6 const method = "POST"; 7 const canonical_url = `/api/v3/adaccounts/${accountId}/media/upload`; 8 const url_parameters = ""; 9 var name = "GAS"; 10 var filename="test.jpeg" 11 var folders = DriveApp.getFoldersByName(name); 12 var folder = folders.next(); 13 var file=folder.getFilesByName(filename).next(); 14 var fileencode=GetBase64Image(file); 15 16 const request_body = { 17 "file": fileencode, 18 "mediaType": "IMAGE" 19 } 20 const endpoint = "https://ads.line.me" + canonical_url + url_parameters; 21 const request_body_json = JSON.stringify(request_body).replace(/:/g, ': ').replace(/,/g, ', '); 22 const content_type = "multipart/form-data"; 23 console.log(request_body_json) 24 const jws_header = encode_with_base64(JSON.stringify({ 25 "alg":"HS256", 26 "kid":access_key, 27 "typ":"text/plain" 28 }).replace(/:/g, ': ').replace(/,/g, ', ')); 29 30 const hex_digest = calc_sha256_digest(""); 31 const payload_date = Utilities.formatDate(today, 'GMT', 'yyyyMMdd'); 32 const payload = `${hex_digest}\n${content_type}\n${payload_date}\n${canonical_url}`; 33 const jws_payload = encode_with_base64(payload); 34 35 const signing_input = `${jws_header}.${jws_payload}`; 36 const encoded_signature = hmacSha256(secret_key, signing_input); 37 const token = `${jws_header}.${jws_payload}.${encoded_signature}`; 38 39 const http_headers = { 40 "Date": Utilities.formatDate(today, 'GMT', 'E, dd MMM yyyy HH:mm:ss z'), 41 "Authorization": `Bearer ${token}`, 42 "Content-Type":content_type 43 } 44 45 const resp = UrlFetchApp.fetch(endpoint, { 46 "headers": http_headers, 47 "method": method, 48 "payload":request_body_json 49 }); 50 51console.log(resp.getContentText()) 52 53} 54 55/** 56 * SHA 256でハッシュ化 57 * @param {string} input - ハッシュ化する文字列 58 * @return {string} - ハッシュ値 59 */ 60function calc_sha256_digest(input) { 61 const rawHash = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, input, Utilities.Charset.UTF_8); 62 let txtHash = ''; 63 for (i = 0; i < rawHash.length; i++) { 64 let hashVal = rawHash[i]; 65 if (hashVal < 0) { 66 hashVal += 256; 67 } 68 if (hashVal.toString(16).length == 1) { 69 txtHash += '0'; 70 } 71 txtHash += hashVal.toString(16); 72 } 73 return txtHash 74} 75 76/** 77 * base64エンコード 78 * @param {string} input - エンコードしたい文字列 79 * @return {string} - base64エンコードされた文字列 80 */ 81function encode_with_base64(input) { 82 return Utilities.base64Encode(input, Utilities.Charset.UTF_8) 83} 84 85/** 86 * HMAC SHA 256でハッシュ化 87 * @param {string} key - ハッシュ化するシークレットキー 88 * @param {string} text - ハッシュ化する文字列 89 * @return {string} - ハッシュ値 90 */ 91function hmacSha256(key, text) { 92 const rowHash = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_256, text, key); 93 return Utilities.base64Encode(rowHash); 94}; 95 96function GetBase64Image(file) 97{ 98 var blob = file.getBlob(); 99 var base64 = Utilities.base64Encode(blob.getBytes()); 100 return base64 101}

試したこと

blobをBase64にせずに、そのまま入れても同じエラーが起きました。

以下のサイトを参考にしてコードを書いたが、同じエラーでした。
ドキュメントにはWhen Content-type is 'multipart/form-data', no 'boundary' value is needed.
と、あるので意味がないと思い消しています。

https://review-of-my-life.blogspot.com/2018/03/multipartform-data-google-apps-script.html

また
payloadに入れるデータをJson化せずにそのまま

"payload":request_body

としても同じエラーでした。。

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.12%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。