2013-04-22 13 views
13

現在、PhonegapでWebスマートフォンアプリケーションを実装しています。このアプリケーションでは、Facebook上で電話カメラで撮影した画像を投稿することができます。この機能は、基本的に64エンコードされたイメージを送信することによって、javascriptを使用してのみ正常に実装されています。今、私はTwitterを使って同じ機能を実装したいと思います。javascriptを使用してPhonegapでTwitterに画像を投稿するには

私はこれについていくつかの非常に興味深いブログ記事を見つけました。私はすでにjavascriptを使ってユーザーステータスを更新することができます...しかし、私もupdate_with_media Twitter Webサービスを使って画像を投稿することはできません。

あまりにもこのpostによると、(PHPスクリプトのような)サーバーサイドコードを使用せずにこの操作を実装することは不可能だと誰かが言います。

私の質問は、javascriptでのみ、update_with_media Twitter Webサービスを使用することができますか?

現在のソリューションの概要を私のコードでお送りします。私はこの記事をワーキングベースとして取り上げました:http://oodlestechnologies.com/blogs/Twitter-integration-on-PhoneGap-using-ChildBrowser-and-OAuth-for-iOS-and-Android-Platforms

ここに私のHTMLコードです。ここ

<!DOCTYPE html> 
<html> 
    <head> 
     <title>Test</title> 
     <script type="text/javascript" src="../js/jquery/jquery.min.js"></script> 
     <script type="text/javascript" src="../cordova-2.5.0.js"></script> 
     <script type="text/javascript" src="../js/childBrowser/childbrowser.js"></script> 
     <script type="text/javascript" src="../js/helpers/jsOAuth-1.3.6.js"></script> 
     <script type="text/javascript" src="../js/helpers/twitter.js"></script> 
    </head> 
    <body> 
     <h4>Oodles Twitter App</h4> 
     <table border="1"> 
      <tr> 
       <th>Login using Twitter</th> 
       <th> 
        <button id="loginBtn" onclick="Twitter.init();">Login</button> 
        <button id="logoutBtn" onclick="logOut();">Logout</button> 
       </th> 
      </tr> 
      <tr id="tweetText"> 
       <td colspan="2"><textarea id="tweet"></textarea></td> 
      </tr> 
      <tr id="tweetBtn"> 
       <td colspan="2" align="right"> 
        <button id="tweeter" onclick="Twitter.tweet();">Tweet</button> 
       </td> 
      </tr> 
      <tr><td colspan="2"><div id="welcome">Please Login to use this app</div></td></tr> 
     </table> 
     <br/> 
     <br/> 
     <button onclick="javascript:location.reload();">Recharger la page</button> 
    </body> 
</html> 

は私twitter.jsコードである:(ポイントがPOSTメソッドである)は、多くの試験(バイナリファイルを送信し、BLOBを送信し、BASE64の画像を送信し、後

$(document).ready(function() { 
    document.addEventListener("deviceready", onDeviceReady, false); 
}); 

function onDeviceReady() { 
    var root = this; 
    cb = window.plugins.childBrowser; 
    if (!localStorage.getItem(twitterKey)) { 
     $("#loginBtn").show(); 
     $("#logoutBtn").hide(); 
     $("tweetBtn").hide(); 
     $("tweetText").hide(); 
    } 
    else { 
     $("#loginBtn").hide(); 
     $("#logoutBtn").show(); 
     $("tweetBtn").show(); 
     $("tweetText").show(); 
    } 

    if (cb != null) { 
     cb.onLocationChange = function(loc) { 
      root.locChanged(loc); 
     }; 
     cb.onClose = function() { 
      root.onCloseBrowser() 
     }; 
     cb.onOpenExternal = function() { 
      root.onOpenExternal(); 
     }; 
    } 
} 

function onCloseBrowser() { 
    console.log("onCloseBrowser!"); 
} 

function locChanged(loc) { 
    console.log("locChanged!"); 
} 

function onOpenExternal() { 
    console.log("onOpenExternal!"); 
} 

// Consumer key : ... 
// Consumer secret : ... 

// GLOBAL VARS 
var oauth; // It Holds the oAuth data request 
var requestParams; // Specific param related to request 
var options = {consumerKey: '...', consumerSecret: '...', callbackUrl: "http://www.google.fr"}; 
var twitterKey = "twtrKey"; // This key is used for storing Information related 
var Twitter = { 
    init: function() { 
     // Apps storedAccessData , Apps Data in Raw format 
     var storedAccessData, rawData = localStorage.getItem(twitterKey); 
     // here we are going to check whether the data about user is already with us. 
     if (localStorage.getItem(twitterKey) !== null) { 
      // when App already knows data 
      storedAccessData = JSON.parse(rawData); //JSON parsing 
      //options.accessTokenKey = storedAccessData.accessTokenKey; // data will be saved when user first time signin 
      options.accessTokenSecret = storedAccessData.accessTokenSecret; // data will be saved when user first first signin 

      // javascript OAuth take care of everything for app we need to provide just the options 
      oauth = OAuth(options); 
      oauth.get('https://api.twitter.com/1/account/verify_credentials.json?skip_status=true', 
        function(data) { 
         var entry = JSON.parse(data.text); 
         console.log("USERNAME: " + entry.screen_name); 
        } 
      ); 
     } 
     else { 
      // we have no data for save user 
      oauth = OAuth(options); 
      oauth.get('https://api.twitter.com/oauth/request_token', 
        function(data) { 
         requestParams = data.text; 
         cb.showWebPage('https://api.twitter.com/oauth/authorize?' + data.text); // This opens the Twitter authorization/sign in page 
         cb.onLocationChange = function(loc) { 
          Twitter.success(loc); 
         }; // Here will will track the change in URL of ChildBrowser 
        }, 
        function(data) { 
         console.log("ERROR: " + JSON.stringify(data)); 
        } 
      ); 
     } 
    }, 
    /* 
    When ChildBrowser's URL changes we will track it here. 
    We will also be acknowledged was the request is a successful or unsuccessful 
    */ 
    success: function(loc) { 

     // Here the URL of supplied callback will Load 

     /* 
     Here Plugin will check whether the callback Url matches with the given Url 
     */ 
     if (loc.indexOf("http://www.google.fr") >= 0) { 

      // Parse the returned URL 
      var index, verifier = ''; 
      var params = loc.substr(loc.indexOf('?') + 1); 

      params = params.split('&'); 
      for (var i = 0; i < params.length; i++) { 
       var y = params[i].split('='); 
       if (y[0] === 'oauth_verifier') { 
        verifier = y[1]; 
       } 
      } 

      // Here we are going to change token for request with token for access 

      /* 
      Once user has authorised us then we have to change the token for request with token of access 
      here we will give data to localStorage. 
      */ 
      oauth.get('https://api.twitter.com/oauth/access_token?oauth_verifier=' + verifier + '&' + requestParams, 
        function(data) { 
         var accessParams = {}; 
         var qvars_tmp = data.text.split('&'); 
         for (var i = 0; i < qvars_tmp.length; i++) { 
          var y = qvars_tmp[i].split('='); 
          accessParams[y[0]] = decodeURIComponent(y[1]); 
         } 

         $('#oauthStatus').html('<span style="color:green;">Success!</span>'); 
         $('#stage-auth').hide(); 
         $('#stage-data').show(); 
         oauth.setAccessToken([accessParams.oauth_token, accessParams.oauth_token_secret]); 

         // Saving token of access in Local_Storage 
         var accessData = {}; 
         accessData.accessTokenKey = accessParams.oauth_token; 
         accessData.accessTokenSecret = accessParams.oauth_token_secret; 

         // Configuring Apps LOCAL_STORAGE 
         console.log("TWITTER: Storing token key/secret in localStorage"); 
         localStorage.setItem(twitterKey, JSON.stringify(accessData)); 

         oauth.get('https://api.twitter.com/1/account/verify_credentials.json?skip_status=true', 
           function(data) { 
            var entry = JSON.parse(data.text); 
            console.log("TWITTER USER: " + entry.screen_name); 
            $("#welcome").show(); 
            document.getElementById("welcome").innerHTML = "welcome " + entry.screen_name; 
            successfulLogin(); 
            // Just for eg. 
            app.init(); 
           }, 
           function(data) { 
            console.log("ERROR: " + data); 
           } 
         ); 

         // Now we have to close the child browser because everthing goes on track. 

         window.plugins.childBrowser.close(); 
        }, 
        function(data) { 
         console.log(data); 


        } 
      ); 
     } 
     else { 
      // Just Empty 
     } 
    }, 
    tweet: function() { 
     var storedAccessData, rawData = localStorage.getItem(twitterKey); 

     storedAccessData = JSON.parse(rawData); // Paring Json 
     options.accessTokenKey = storedAccessData.accessTokenKey; // it will be saved on first signin 
     options.accessTokenSecret = storedAccessData.accessTokenSecret; // it will be save on first login 

     // javascript OAuth will care of else for app we need to send only the options 
     oauth = OAuth(options); 
     oauth.get('https://api.twitter.com/1/account/verify_credentials.json?skip_status=true', 
       function(data) { 
        var entry = JSON.parse(data.text); 
        Twitter.post(); 
       } 
     ); 
    }, 
    /* 
    We now have the data to tweet 
    */ 
    post: function() { 
     alert('Post !'); 
     var theTweet = $("#tweet").val(); // You can change it with what else you likes. 

     oauth.post('https://upload.twitter.com/1/statuses/update_with_media.json', 
       { 
        'status': theTweet, 
        'media': //HERE IS THE PROBLEM, WHAT TO DO HERE ? 
       }, "multipart/form-data", 
       function(data) 
       { 
        alert('Data 1 !'); 
        console.log('------Data1 : ' + data); 
        var entry = JSON.parse(data.text); 
        console.log(entry); 
        done(); 
       }, 
       function(data) { 
        //var json_result = JSON.parse(data); 
        //alert(json_result.text.error); 
        var entry = JSON.stringify(data); 
        console.log('------Data2 : ' + entry); 
       } 
     ); 
    } 

} 

function done() { 
    alert("OKKK !"); 
    $("#tweet").val(''); 
} 


function successfulLogin() { 
    $("#loginBtn").hide(); 
    $("#logoutBtn,#tweet,#tweeter,#tweetBtn,#tweetText").show(); 

} 

function logOut() { 
    //localStorage.clear(); 
    window.localStorage.removeItem(twitterKey); 
    document.getElementById("welcome").innerHTML = "Please Login to use this app"; 
    $("#loginBtn").show(); 
    $("#logoutBtn,#tweet,#tweeter,#tweetText,#tweetBtn").hide(); 

} 

{\ "エラー\":[{\ "メッセージ\":} 131: "内部 エラー\"、\ "コード\" \を..)ここで私はTwitterからのリターンメッセージであります] "、" xml ":" "、" requestHeaders ":{" Content-Type ":"マルチパート/フォームデータ "}、" responseHeaders ":{" date ":" Fr i、 19 4月2013 15:45:28 GMT "、" content-encoding ":" deflate "、" strict-transport-security ":" max-age = 631138519 "、" status ":" 500 内部サーバー エラー "、" server ":" tfe "、" content-type ":" application/json; のcharset = UTF-8" 、 "バージョン": "HTTP/1.1"}}

A "のTwitterのdevのフォーラムに掲載さが、私のために働いていないされている(ブロブを送信することによって)ソリューション":DEV .twitter.com /議論/ 6969

誰もが同じ機能を実装したり、解決策を持っていたいんありがとう

を------ EDITED:?!

私はしたいですJavascriptとIサーバー側のソリューション(PHP、C#、Javaなどはありません)を実装したくありません。

+0

PhoneGapフレームワークを正しく使用していますか? JavaScriptアクションをネイティブコードにフックできるプラグイン(http://docs.phonegap.com/en/2.7.0/guide_plugin-development_index.md.html#Plugin%20Development%20Guide)を構築することができます。しかし、サービスラッパー(php、asp)を1つの言語で記述するのではなく、ネイティブコード(ios、android、wpなど)を書くことになります。必要なファイルを作成するサービスラッパーを作成することをお勧めします。 – Markus

+0

これについてさらに読んだことがあります。このようなことを調べたことがありますか?var pngData = canvas.toDataURL();そして、探しているデータだけにコンテンツをトリムする必要があります。 – Markus

+0

投稿したい画像は、実際にはHTMLページの一部をHTML5キャンバスに変換し、toDataURL()メソッドからキャンバスのbase64表現を取得することで生成されます。 – Antoine

答えて

1

ドキュメントによれば、Twitterはmultipart/form-dataエンコードタイプを必要とします。つまり、ベース64文字列は機能しません。

POSTステータス/更新とは異なり、このメソッドは生のマルチパートデータを必要とします。あなたのPOSTリクエストのContent-Typeが〜https://dev.twitter.com/docs/api/1/post/statuses/update_with_media

しかし、あなたは、BASE64をとり、実際のファイルに変換し、転送エンドポイントをホストする可能性があり、メディア[]パラメータでmultipart/form-dataに設定する必要がありますTwitterへのリクエスト。例えば(未テスト):

<?php 

$base64 = $_POST['image']; 
$data = base64_decode($base64); 

// Make name unique to avoid conflicts. 
$temp_file = uniqid() . $_POST['name']; 

// Save the file to a temp location. 
file_put_contents($temp_file, $data); 

$temp_info = pathinfo($temp_file); 
$temp_type = $temp_info['extension']; 
$temp_name = basename($temp_file, '.' . $temp_type); 

// OAuth library recommended by Twitter: https://github.com/themattharris/tmhOAuth 
// See original: https://github.com/themattharris/tmhOAuth-examples/blob/master/images.php 

require 'tmhOAuth.php'; 
require 'tmhUtilities.php'; 

$tmhOAuth = new tmhOAuth(array(
    'consumer_key' => $_POST['consumer_key'], 
    'consumer_secret' => $_POST['consumer_secret'], 
    'user_token'  => $_POST['user_token'], 
    'user_secret'  => $_POST['user_secret'], 
)); 

// note the type and filename are set here as well 
// Edit: Not sure if the `type` and `filename` params are necessary. 
$params = array('media[]' => "@{$temp_file};type={$temp_type};filename={$temp_name}"); 

$code = $tmhOAuth->request('POST', $tmhOAuth->url('1/status/update_with_media'), 
    $params, 
    true, // use auth 
    true // multipart 
); 

// Remove temp file. 
unlink($temp_file); 

if ($code == 200) { 
    tmhUtilities::pr(json_decode($tmhOAuth->response['response'])); 
} 
tmhUtilities::pr(htmlentities($tmhOAuth->response['response'])); 

?> 

そして、あなたが好きそれを呼ぶかもしれない:クライアントのJSを使用してTwitterへ画像を投稿しようとしている人のため

$.ajax({ 
     // You'll want to use https to protect the oauth info. 
     url: "https://mysite.com/proxy.php", 
     type: "POST", 
     data: { 
      image: "base64 data...", 
      name: "foo.png", 
      consumer_key: options.consumerKey, 
      consumer_secret: options.consumerSecret, 
      user_token: options.accessTokenKey, 
      user_secret: options.accessTokenSecret 
     }, 
     success: function(data) { 
      console.log(data); 
     } 
    }); 
+0

私はこれを行うためにサーバー側のコードを使用したくありません。私はすでにPHPのように実際のファイルで完全に動作するC#ソリューションを実装しましたが、それは重要ではありません。私はちょうどJavascriptコードを使用したい。 – Antoine

+1

あなたがファイルをアップロードするために 'input'要素を使用せず、あなたが作業するbase64データしか持っていないと仮定すると、ブラウザは現在、base64文字列を変換する方法がないので不可能ですファイルアップロード。入力要素を使用していた場合、iframe手法を使用するか、データを直接送信することができます(HTML5ブラウザのみ)が、そうではありません。 –

+1

Twitterに「生成済み」の画像を投稿したいので、私はinput要素を使用しません。ユーザーは、ギャラリーまたは電話ファイルシステムで画像を選択しません。イメージは、HTMLページの一部をHTML5キャンバスに変換し、次に 'toDataURL()'メソッドからキャンバスのbase64表現を取得することによって生成されます。この情報を持ったアイデア? – Antoine

0

を、私はして溶液を使用してTwitterに投稿することができましたgary-buynary-co-za(https://github.com/bytespider/jsOAuth/pull/11)がこのフォーラムの最後に追加されました。結局、Phonegap FileTransferとFileTransferOptionsオブジェクトを使ってtwitter apiに画像を転送しましたが、FileTransferOptionsヘッダとシグネチャを準備するためにjsOAuthを使用しました。ソリューションは間違いなくクリーンアップすることができます。

関連する問題