Hello World!
Hello World!
よ☆ろ☆し☆く☆ね
RubyでDropboxAPIを使ってFileアップロード
手順その1.アプリ登録
まずはこちらからアプリを登録。プラットフォームとかいろいろあるけどとりあえずほっとき、重要なのはkeyとsecret。コレをどこかにメモしときます。そもそもDropboxに登録してないぜ!って場合はそこから…
手順その2.アクセストークン、シークレット取得
こちらにドキュメンテーションがあるので読んでみる(英語か…)。とりあえず「/token」のところかな?リクエストメソッドはGet・Postどちらでもいいみたいだけど、まあ普通Postでしょう。必須パラメータはemailとpasswordとある。というわけでこの2つをPostのbodyとしてリクエストを送ってみると…エラー!そもそもkeyとsecret使って無いじゃないか!もうちょっとよく読んでみるとなにやら英語で書いてあるけど具体的にどうすればよいのかよくわかりません…とりあえずbodyにoauth_consumer_keyとoauth_consumer_secretという名前でくっつけてリクエストを投げてみると…なんと成功!まじかww
(ここでのbody: email=xxxx&password=xxxx&oauth_consumer_key=xxxx&oauth_consumer_secret=xxxx)
さすがにどうかと思うのでヘッダに付けて加えてbodyから除いてみた(Authorization: OAuth oauth_consumer_key="xxxx", oauth_consumer_secret="xxxx")。これでも成功。なんでもありだなw
とりあえずこれでアクセストークンとアクセストークンシークレット取得成功!?
手順その3.ファイルアップロード
ここが今回の目標。ドキュメンテーションの「/files」というところを見てみる。URLが2つあるけど?とりあえず上のやつを使ってみよう。そしてまた情報少ないな…Fileのアップロードってどうやるんだっけ?と思いつつ昔作ったプログラムを見ながら改造して…とりあえずアップする部分はこんな感じでいけるかな?
uri=URI.parse(requestURL) https=Net::HTTP.new(uri.host,uri.port) https.use_ssl=true https.verify_mode=OpenSSL::SSL::VERIFY_NONE req=Net::HTTP::Post.new(uri.path) req["authorization"]=header req["content-type"] ="multipart/form-data; boundary=#{boundary}" body=Array.new body << "--#{boundary}" body << "content-disposition: form-data; name=\"file\"; filename=\"sample.html\"" body << "" body << file body << "--#{boundary}--" body << "" req.body=body.join("\r\n") return https.start.request(req)
でやってみたらエラー!timestampがないとか言ってやがる…。てことはTwitterと同じやり方でやるのか??と思ってこれまた昔作ったTwitterプログラムを引っ張り出す。で適当に改造して作ったのが以下。
require "net/https" require "base64" require "openssl" require "erb" module Dropbox module Signature CONSUMER_KEY="xxxx" CONSUMER_SECRET="xxxx" SIGNATURE_METHOD="HMAC-SHA1" OAUTH_VERSION="1.0" def self.makeHeader(str) ret=Array.new str.split("&").each{|elem| ret << "#{elem.split("=")[0]}=\"#{elem.split("=")[1]}\"" } return ret.join(",") end def self.getTimeStamp return Time.now.tv_sec end def self.getNonce ret=Array.new size=8 for i in 0..size-1 case rand(3) when 0 #a-z ret[i]=(97+rand(26)).chr when 1 #A-Z ret[i]=(65+rand(26)).chr when 2 #0-9 ret[i]=(48+rand(10)).chr; end end return ret.join("") end def self.getSignature(signatureBaseString, keyString) digest=OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new,keyString,signatureBaseString) signature=ERB::Util.u((Base64.encode64(digest)).chomp) return signature end def self.encode(str) return (ERB::Util.u(str)).gsub("%7E","~") end end module File def self.upLoad(accessToken,accessTokenSecret,filestr,path) requestURL="https://api-content.dropbox.com/0/files/dropbox/#{path}" requestParameters="file=sample.html&oauth_consumer_key=#{Signature::CONSUMER_KEY} &oauth_nonce=#{Signature::getNonce()}&oauth_signature_method=#{Signature::SIGNATURE_METHOD} &oauth_timestamp=#{Signature::getTimeStamp()}& oauth_token=#{accessToken}&oauth_version=#{Signature::OAUTH_VERSION}" signatureBaseString="POST&#{Signature::encode(requestURL)}&#{Signature::encode(requestParameters)}" keyString="#{Signature::CONSUMER_SECRET}&#{accessTokenSecret}" signature=Signature::getSignature(signatureBaseString,keyString) header="OAuth #{Signature::makeHeader(requestParameters)},oauth_signature=\"#{signature}\"" uri=URI.parse(requestURL) https=Net::HTTP.new(uri.host,uri.port) https.use_ssl=true https.verify_mode=OpenSSL::SSL::VERIFY_NONE boundary=Time.now.strftime("%Y%m%d_%H%M%S_#{$$}") req=Net::HTTP::Post.new(uri.path) req["authorization"]=header req["content-type"] ="multipart/form-data; boundary=#{boundary}" body=Array.new body << "--#{boundary}" body << "content-disposition: form-data; name=\"file\"; filename=\"sample.html\"" body << "" body << filestr body << "--#{boundary}--" body << "" req.body=body.join("\r\n") return https.start.request(req) end end end token="xxxx" secret="xxxx" path="xxxx" file="watashihabaka" res=Dropbox::File.upLoad(token, secret, file, path) puts res.code #=>200 puts res.body #=>{"result": "winner!"}
これでアップロード成功。「winner!」ってなんだw ていうか各プラットフォーム毎にSDK?も提供されてるしそれを使えという話も…
ということで第1回DropboxAPIでファイルアップロードでした^^
しかし汚いソース載せるの恥ずかしいな…w改善した方がいいところとかバシバシ教えてください!
ちなみにこれは開発用のものであって正式に使うためには「公開申請」とやらをしなければならないらしいです(開発用は自分のアカウントにしかアクセスできない、回数制限がかかる等の問題あり)