2013-04-22 3 views
13

현재 Phonegap으로 웹 스마트 폰 응용 프로그램을 구현 중입니다. 이 응용 프로그램에서 사용자는 페이스 북에 전화 카메라로 찍은 이미지를 게시 할 수 있습니다. 이 기능은 기본 64 인코딩 이미지를 전송하여 자바 스크립트 만 사용하여 성공적으로 구현되었습니다. 이제는 Twitter를 사용하여 동일한 기능을 구현하려고합니다.자바 스크립트를 사용하여 Phonegap의 트위터에 이미지를 게시하는 방법

나는 이것에 관해 매우 흥미로운 블로그 게시물을 발견했으며 이미 자바 스크립트 만 사용하여 사용자 상태를 업데이트 할 수 있습니다.하지만 update_with_media Twitter 웹 서비스를 사용하여 이미지를 게시 할 수 없습니다.

too post에 따르면 누군가는 서버 측 코드 (예 : PHP 스크립트)를 사용하지 않고이 작업을 구현하는 것이 불가능하다고 말합니다.

제 질문은 자바 스크립트에서만 update_with_media Twitter 웹 서비스를 사용할 수 있습니까?

현재 솔루션에 대한 개요를 보려면 내 코드를 보내주십시오. 이 기사를 작업 기반으로 사용했습니다. 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로 이미지를 전송 이진 파일을 전송하는 방울을 보낸 후. ..) 여기에 트위터의 리턴 메시지는 내가 가지고있다 :

{\ "오류 \": [{\ "메시지 \"\ "내부 오류 \", \ "코드 \": 131} } ","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; 문자셋 = UTF-8 ","버전 ":"HTTP/1.1 "}}

A"트위터 dev에 포럼에 게시하지만 나를 위해 작동하지 않는 한 (블롭를 전송하여) 솔루션 "DEV .twitter.com/토론/6969

사람이 같은 기능을 구현하거나 해결책을 가지고 감사 할합니까

을 ------ 편집 :?!

난 그냥 원하는 자바 스크립트과 I 서버 측 솔루션 (PHP, C#, Java는 지원하지 않음)을 구현하고 싶지는 않습니다.

+0

PhoneGap 프레임 워크를 올바르게 사용하고 있습니까? 자바 스크립트 액션을 네이티브 코드에 연결할 수있는 플러그인 (http://docs.phonegap.com/en/2.7.0/guide_plugin-development_index.md.html#Plugin%20Development%20Guide)을 빌드하는 방법을 살펴볼 수 있습니다. 그러나 서비스 래퍼 (php, asp)를 하나의 언어로 작성하는 대신 원시 코드 (ios, android, wp 등)를 작성해야합니다. 나는 당신이 요구하는 것이 아니지만, 당신이 필요로하는 파일을 생성하는 서비스 래퍼를 작성하는 것을 권하고 싶다. – Markus

+0

자세한 내용은 여기를 참조하십시오. 이'var pngData = canvas.toDataURL(); '과 같은 일을 쳐다 보았습니까? 그러면 원하는 데이터 만 내용을 다듬어야합니다. – Markus

+0

게시하고 싶은 이미지는 실제로 HTML 페이지의 일부를 HTML5 캔버스로 변환 한 다음 toDataURL() 메소드에서 캔버스의 base64 표현을 검색하여 생성됩니다. – Antoine

답변

1

문서에 따르면 트위터에는 multipart/form-data enctype이 필요합니다. 즉, base64 문자열은 작동하지 않습니다.

POST 상태/업데이트와 달리이 메서드는 원시 다중 파트 데이터를 필요로합니다.귀하의 POST 요청의 콘텐츠 유형은 당신이 진짜 파일로 변환, base64로 소요 엔드 포인트를 호스팅 할 수 https://dev.twitter.com/docs/api/1/post/statuses/update_with_media

그러나 미디어 [] 매개 변수 ~에 multipart/form-data로 설정하고 전달해야한다 트위터에 요청하십시오. (테스트되지 않은) 예를 들면 :

<?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를 사용하여 트위터에 이미지를 게시하려고 사람들을위한

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

, 내가 용액을 사용하여 트위터에 게시 할 수 있었다 gary-buynary-co-za (https://github.com/bytespider/jsOAuth/pull/11)이 포럼의 끝에 있습니다. 꽤 많이, FileTransferOptions 헤더와 서명을 준비하기 위해 jsOAuth를 사용하여 PhoneTap FileTransfer와 FileTransferOptions 객체를 사용하여 이미지를 트위터 API로 전송했습니다. 솔루션을 확실히 정리할 수 있습니다.

관련 문제