2013-04-22 82 views
13

我目前正在使用Phonegap实现网页智能手机应用程序。在此应用程序中,用户可以使用Facebook上的手机照相机发布图像。此功能已成功实施,只使用JavaScript,通过发送基地64编码图像。现在,我想使用Twitter实现相同的功能。如何在使用javascript的Phonegap上的twitter上发布图像

我发现这个一些非常有趣的博客文章,我已经能够更新只使用JavaScript的用户身份...但也使用Twitter的update_with_media 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代码:(重点是在后法)

$(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(); 

} 

经过多次测试(发送一个base64图像,发送一个blob,发送一个二进制文件。 ..)这里是从Twitter返回的消息我:

{\ “错误\”:[{\ “消息\”:\ “内部 错误\”,\ “代码\”:131} ]} “ ”XML“: ”“, ”requestHeaders“:{ ”内容类型“: ”多部分/格式数据“}, ”responseHeaders响应“:{ ”日期“:” FR我, 2013年4月19日15点45分28秒 GMT“‘内容编码’:‘放气’,‘严格的运输安全’:‘最大年龄= 631138519’,‘状态’:” 500 内部服务器 错误“,”server“:”tfe“,”content-type“:”application/json; 的charset = UTF-8" , “版本”: “HTTP/1.1”}}

一个 “解决方案”(由发送BLOB)已张贴在Twitter上开发论坛,但不是为我工作了:dev .twitter.com /讨论/ 6969

有谁要实现相同的特征或有解决的办法谢谢

------编辑:?!

我只是想使用Javascript和I不希望实现任何服务器端解决方案(无PHP,C#,Java ...)。

+0

您是否正确使用PhoneGap框架?您可以查看构建插件(http://docs.phonegap.com/en/2.7.0/guide_plugin-development_index.md.html#Plugin%20Development%20Guide),该插件允许您将JavaScript操作绑定到本机代码。然而,你会写本地代码(ios,android,wp等)而不是用一种语言编写服务包装器(php,asp)。我建议,尽管这不是你要求的 - 编写一个服务包装来创建你需要的文件。 – Markus 2013-05-06 19:56:10

+0

了解更多关于此。你是否研究过这样的事情:'var pngData = canvas.toDataURL();'然后你需要将内容修剪为你正在查找的数据。 – Markus 2013-05-06 20:18:41

+0

我想发布的图像实际上是通过将HTML页面的一部分转换为HTML5画布,然后从toDataURL()方法检索画布的base64表示形式生成的... – Antoine 2013-05-07 07:28:28

回答

1

根据该文档,Twitter的要求multipart/form-data加密类型,这意味着一个base64字符串行不通的。

与POST状态/更新不同,此方法需要原始多部分数据。您的POST请求的Content-Type应该设置为multipart/form-数据与媒体[]参数〜https://dev.twitter.com/docs/api/1/post/statuses/update_with_media

然而,你可能拥有一个端点需要的base64,将其转换为一个真正的文件,并转发请求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'])); 

?> 

,你可能会这样称呼它:

$.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

我不想使用任何服务器端代码来执行此操作。我已经实现了一个C#解决方案,完全可以像在PHP中一样使用真实文件,但这不是重点。我只想使用Javascript代码。 – Antoine 2013-05-03 12:06:33

+1

假设您没有使用'input'元素来上传文件,并且只有base64数据可以使用,我相信您要做的事情是不可能的,因为浏览器目前没有办法将base64字符串到文件上传。如果您使用的是输入元素,则可以使用iframe技术或直接发送数据(仅限HTML5浏览器),但事实并非如此。 – 2013-05-03 16:37:09

+1

我不使用任何'input'元素,因为我想在Twitter上发布“生成”图像。用户不要在其图库或电话文件系统中选择图像。通过将HTML页面的一部分转换为HTML5画布,然后从'toDataURL()'方法检索画布的base64表示,生成图像。有关这些信息的任何想法? – Antoine 2013-05-06 07:52:10

0

对于任何人尝试使用客户端JS,发布图片到Twitter,我能够发布使用该解决方案叽叽喳喳gary-buynary-co-za(https://github.com/bytespider/jsOAuth/pull/11)在这个论坛结束。使用Phonegap FileTransfer和FileTransferOptions对象将图像传输到twitter api,但使用jsOAuth来准备FileTransferOptions标头和签名。解决方案绝对可以清理干净。

相关问题