dポイントプレゼントキャンペーン実施中!

tmhOAuthとTwitterAPIを使ってサーバーに保存してある画像をtwitterに投稿したいと考えています。
tmhOAuthを使ってつぶやき(文字列)の投稿は成功しています。
画像の投稿になるとうまく行きません。ウェブ上で情報を探せるだけ探して数日間トライしてみましたが、どれも成功には至りませんでした。


「開発環境」
PHP:5.5
Cakephp:2.5

function test(){

$twConf = array(
'consumer_key' => 'xxxxxxxxxxxxxxxxxxxxxxx',
'consumer_secret' => 'xxxxxxxxxxxxxxxxxxxxxxx',
'user_token' => 'xxxxxxxxxxxxxxxxxxxxxxx',
'user_secret' => 'xxxxxxxxxxxxxxxxxxxxxxx',
'curl_ssl_verifypeer' => false,
);


$tmhOAuth = new tmhOAuth($twConf);
$image ='http://www.example.com/img/test.jpg';
$message='hoge hoge';
$params = array(
'media[]' => "@{$image}",
'status' => "{$message}"
);
$code = $tmhOAuth->request('POST', $endpoint, $params, true, true);
if ($tmhOAuth->response["code"] == 200){
var_dump($tmhOAuth->response["response"]);
} else {
var_dump($tmhOAuth->response["error"]);
}
}

このソースを実行するとエラーレスポンスが返らずに$codeの中身は403となります。
(何かのエラーが返ってきているようです)

上記のやり方以外にも
----------------------------------------------------------------
$file = 'http://www.example.com/img/test.jpg';
$image = file_get_contents( $file );
$imagesize = getimagesize( $file );
$content_base64 = base64_encode($image);

$api_url = 'https://api.twitter.com/1.1/statuses/update_with …
$params = array(
'status' => $message,
'media[]' => $content_base64 . ";type=" . $imagesize['mime'] . ";filename=" . basename( $file ),
);
----------------------------------------------------------------
という方法を行ってみましたが、エラーが「0」という形で返ってきてしまいます。


twitter developersのwebsite・Callback URLは自分のドメイン名を設定しています。アクセスレベルは「Read and write」です。
文字の投稿はできているので、$params 周辺の記載に問題があると考えています。

TwitterAPI関係に詳しい方がおられましたら、よい方法を教えていただければと思います。
宜しくお願い致します。

A 回答 (1件)

【解決策】



リモートパスは「@」では指定できないようです。正しくは、テンポラリファイルにリモートデータを書き込んだあと、そのパスを指定します。

$twConf = [
....'consumer_key' => 'xxx',
....'consumer_secret' => 'xxx',
....'user_token' => 'xxx',
....'user_secret' => 'xxx',
....'curl_ssl_verifypeer' => false,
];
$endpoint = 'https://api.twitter.com/1.1/statuses/update_with …
$status = 'hoge hoge';
$media = 'http://www.example.com/img/test.jpg';
$tmhOAuth = new tmhOAuth($twConf);
$tmp = tmpfile();
stream_copy_to_stream(fopen($media, 'rb'), $tmp);
$params = [
....'status' => $status,
....'media[]' => '@' . stream_get_meta_data($tmp)['uri'],
];
$tmhOAuth->request('POST', $endpoint, $params, true, true);
var_dump(json_decode($tmhOAuth->response['response']));

実際には、のちに説明する問題上、ツイートの前に常に半角スペースを付加すべきです。

$twConf = [
....'consumer_key' => 'xxx',
....'consumer_secret' => 'xxx',
....'user_token' => 'xxx',
....'user_secret' => 'xxx',
....'curl_ssl_verifypeer' => false,
];
$endpoint = 'https://api.twitter.com/1.1/statuses/update_with …
$status = 'hoge hoge';
$media = 'http://www.example.com/img/test.jpg';
$tmhOAuth = new tmhOAuth($twConf);
$tmp = tmpfile();
stream_copy_to_stream(fopen($media, 'rb'), $tmp);
$params = [
....'status' => ' ' . $status,
....'media[]' => '@' . stream_get_meta_data($tmp)['uri'],
];
$tmhOAuth->request('POST', $endpoint, $params, true, true);
var_dump(json_decode($tmhOAuth->response['response']));


【そもそも「POST statuses/update_with_media」が非推奨である】

・複数画像アップロードのためには「media[]」という同名のキーを複数セットするように当初は設計されていたが、連想配列(ハッシュ)で同名のキーを扱えるプログラミング言語がそうそう無い。
・マルチパートリクエスト送信に関して、PHPのcURL関数の設計に問題があり、そのことについて全く考慮が為されていない手抜きライブラリがあまりにも普及しすぎてしまった。(tmhOAuthもそのうちの1つ)

http://qiita.com/mpyw/items/c2d2f9cf67072e926721

このような背景があり、このエンドポイントは複数画像アップロード可能になることもなく非推奨にされたようです。TwitterAPIのドキュメントを見るとしっかり「Deprecated」と書かれています。

https://dev.twitter.com/rest/reference/post/stat …

現在は以下の方法が推奨されています。

https://dev.twitter.com/rest/public/uploading-me …

・1枚ずつアップロードし、更にツイートを実行するリクエストはアップロードとは別に必要なため、必ず2回以上のリクエストが発生します。
・パラメータ名が「media[]」ではなく「media」であることに注意してください。
・画像データは、非マルチパートの場合はBASE64エンコードしてセットします。マルチパートの場合は何もせずそのままセットします。以前はマルチパート必須でしたが、新しいエンドポイントはどちらでも受け付けるようになっています。「media」と「status」は混在しないため、どちらを採用しても以前発生していたようなcURL関数特有の問題は発生しません。


【宣伝: もっと洗練されたライブラリ、使ってみませんか?】

https://github.com/mpyw/TwistOAuth

[旧いエンドポイントを使う場合]

try {
....$to = new TwistOAuth('xxx', 'xxx', 'xxx', 'xxx');
....var_dump($to->postMultipart('statuses/update_with_media', [
........'status' => 'hoge hoge',
........'@media[]' => 'http://www.example.com/img/test.jpg',
....]));
} catch (TwistException $e) {
....var_dump($e->getMessage());
}

[新しいエンドポイントを使う場合]

try {
....$to = new TwistOAuth('xxx', 'xxx', 'xxx', 'xxx');
....var_dump($to->post('statuses/update', [
........'status' =>
............'hoge hoge',
........'media_ids' =>
............$to->postMultipart('media/upload', [
................'@media' => 'http://www.example.com/img/test.jpg',
............])->media_id_string,
....]));
} catch (TwistException $e) {
....var_dump($e->getMessage());
}
    • good
    • 0
この回答へのお礼

To_aru_User様

詳しいご回答ありがとうございました。
ここまで詳しく書いていただけると、だいぶ前に進むことができそうです。
「Uploading Media: Multiple Photos」が推奨ということも知りませんでした。
理解するのには時間がかかりそうですが、ひとつひとつ理解を深めていきたいと思います。

お礼日時:2015/01/08 01:54

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!