読者です 読者をやめる 読者になる 読者になる

あんパン

こしあん以外は認めない

JavaScriptでTwitterに画像を投稿する

Firefox OSTwitter APIライブラリを作っているという話は前述の通り。

Violet.jsをアップデートしている - あんパン

すっかり忘れていたけれど、es6-promiseとか使うとWindowsVisual Studio(JavaScript)を使った開発でもこのviolet.jsを使うことができる。

閑話休題Twitterに画像を投稿する方法は2つ。

  • POST statuses/update_with_mediaを使う
  • POST media/uploadを使ってから、POST statuses/updateを使う

前者はすでにdeprecatedなので、今後作られるTwitterクライアントでは後者を採用するのが望ましい。ここでは後者について解説する。

POST media/uploadで写真を送信する

POST media/uploadでは写真を1枚ずつmultipart/form-dataで送信する。返り値のmedia_idをPOST statuses/updateの引数に渡すことで画像のツイートを行うことができる。

Authorizationヘッダの生成

投稿には当然OAuthが必要になる。oauth_signatureの作り方等は以前紹介しているのでこちらを参照のこと。

Twitterと認可 - あんパン

必要なOAuthパラメータは以下の通り

  • oauth_consumer_key
  • oauth_nonce
  • oauth_signature
  • oauth_signature_method
  • oauth_timestamp
  • oauth_token
  • oauth_version

通常、POSTリクエストでRESTエンドポイントを叩く場合はリクエストボディもsignatureの生成時にパラメータに含める必要があるが、POST media/uploadの場合は必要ない。それ以外は通常どおりの認証プロセスとなる。

これ以降はOAuthの認証は突破できたものとして扱う。

JavaScriptでファイルを送信する

XMLHttpRequest Level2から、send時にFormDataを引数に渡すことにより自動的にmultipartで送信されるようになっている。

サンプルコード

HTML
<input type="file" id="file">
JavaScript
var data = document.querySelector('#file').files;
var fd = new FormData();

// mediaパラメータが必須なので、第一引数は必ずmedia
fd.append("media", data[0]);

var xhr = new XMLHttpRequest({mozSystem: true});
xhr.open("POST", "https://upload.twitter.com/1.1/media/upload.json", true);
xhr.setRequestHeader('Authorization', /* 生成したOAuthのヘッダ */);
xhr.send(fd);
xhr.addEventListener('load', function() {
  console.log(JSON.parse(xhr.responseText));
});

勢い的にはこのようなコードで良い。注意点として

  • FQDNapi.twitter.comではなくupload.twitter.com
  • xhr.setRequestHeaderでmultipart/form-dataを指定する必要はない
    • FormDataを引数にすると自動でmultipart/form-dataになる
    • 自前で指定するとbounderyが指定されずBad Requestが返る

リクエストに成功するとmedia_idを含むJSONが返る。

POST statuses/updateで写真を投稿する

前項で得たmedia_id_strをPOST statuses/updateの引数に含める。media_idsにmedia_id_strを指定する。複数指定したい場合はカンマで繋げば良い。

まとめ

以上がJavaScriptTwitterに画像を投稿する概略である。violet.jsのdevelopブランチに同様のコミットを追加しているので分からないことがあればこれを参照すると良い。

masawada/violet at develop · GitHub

--- 追記 ---

JavaScriptでTwitterに画像を投稿する - あんパン

手でmultipart/form-data指定するとboundery空になるの不思議な感じする.手でboundary指定したらどうなるんだろ

2015/02/01 18:24

手でmultipart/form-data指定するとboundery空になるの不思議な感じする.手でboundary指定したらどうなるんだろ - side_tana のコメント / はてなブックマーク

setRequestHeaderを行わないでおくと自動で以下のようなContent-Typeが設定される。

Content-Type: "multipart/form-data; boundary=---------------------------84533449419325157531249583443"

自前でsetRequestHeaderするとこれがmultipart/form-dataで上書きされてしまうのでboundaryを識別できずmediaパラメータがないというエラー(Bad Request)が返ってくる。

setRequesHeaderでmultipart/form-data; boundary=...というような設定すれば良いのだろうがそもそもFormDataをsendする際にboundaryを自動生成してくれるため、それを知る術がなく設定ができないという話でした。

あと綴りboundaryだった。