Uploading photos to Facebook with RFacebook
Posted on June 13, 2008 - Filed Under Facebook, Ruby, RubyOnRails
I’m quite busy recently, and as result I write posts on my blogs with smaller frequency as I usually did… But there are few interesting topics I want to write about. First - RFacebook and photos upload.
I’m using RFacebook gem to handle calls to Facebook API. But recently I found out, that probably there is no way to upload photos to Facebook with RFacebook. The reason is that API call is special case and as far as I know, there is no code for that in RFacebook.
So we need to extend RFacebook by ourself. Problem with facebook.photos.upload is that need to be multi-part encoded post, that means MIME encoding. Since this is one way post, we don’t need any specialized library to handle MIME thus we will prepare own code. To make HTTP request Net::HTTP Ruby library is obvious choice, however it does not support multiparts.
First - Google, and I found this post describing how to make multiparts with Net::HTTP.
Next we need to extend RFacebook::FacebookWebSession providing photos_upload method. RFacebook uses method_missing to handle calls to API, providing own method photos_upload will skip default processing flow:
module RFacebook
class FacebookWebSession
def photos_upload(params = {})
params = (params || {}).dup
params[:method] = "facebook.photos.upload"
params[:api_key] = FACEBOOK["key"]
params[:v] = API_VERSION
params[:session_key] = session_key
params[:call_id] = Time.now.to_f.to_s
file = params.delete :file
params[:sig] = signature(params)
boundary = 'some_long_and_random_string_which_wont_show_in_data_stream'
params_as_arr = []
params.each {|k,v| params_as_arr << text_to_multipart(k,v)}
params_as_arr << file_to_multipart('filename', 'somefile', 'image/jpg', file)
qry = params_as_arr.collect {|p|
'--' + boundary + "\r\n" + p
}.join('') + "--" + boundary + "--\r\n"
handle_xml_response(
Net::HTTP.start(API_HOST).post2(
API_PATH_REST,
qry,
"Content-type" => "multipart/form-data; boundary=" + boundary).response.body.to_s
)
end
end
private
def text_to_multipart(key,value)
return "Content-Disposition: form-data; name=\"#{key.to_s}\"\r\n" +
"\r\n" +
"#{value}\r\n"
end
def file_to_multipart(key,filename,mime_type,content)
return "Content-Disposition: form-data; name=\"#{key.to_s}\"; filename=\"#{CGI::escape(filename)}\"\r\n" +
"Content-Transfer-Encoding: binary\r\n" +
"Content-Type: #{mime_type}\r\n" +
"\r\n" +
"#{content}\r\n"
end
end
Now assuming that fbsession is valid Facebook session we use it providing :file with raw data and :caption for description to Facebook:
fbsession.photos_upload :file => File.read("SOME_PATH_TO_FILE.jpg"),
:caption => 'some caption'
As You can see this is very ‘rough’ solution, just to give You idea where to head next (error checking, handle other MIME types than image/jpeg, etc).
Please give me You thoughts on that code - if there will be some response I will feel obligated to prepare some more quality code to submit it as patch to RFacebook :)))
Popularity: 32% [?]
Hits for this post: 8139
Similar Posts
- Interacting with Facebook without user
- Rails, threads and Facebook
- Skinny controller, fat model and Facebook
- FriendsFeedMe on new gem
- Using non text values as arguments in functional tests
Comments
4 Responses to “Uploading photos to Facebook with RFacebook”
Leave a Reply




Hi,
I am trying this code like this. but I am getting an error
“can’t dup Symbol
RAILS_ROOT: E:/Rails2.2/integrateSNS
Application Trace | Framework Trace | Full Trace
E:/ruby/lib/ruby/gems/1.8/gems/rfacebook-0.9.8/lib/facebook_session.rb:177:in `dup’
E:/ruby/lib/ruby/gems/1.8/gems/rfacebook-0.9.8/lib/facebook_session.rb:177:in `remote_call’
E:/ruby/lib/ruby/gems/1.8/gems/rfacebook-0.9.8/lib/facebook_session.rb:164:in `method_missing’
E:/ruby/lib/ruby/gems/1.8/gems/rfacebook-0.9.8/lib/facebook_web_session.rb:138:in `photos_upload’
E:/ruby/lib/ruby/gems/1.8/gems/rfacebook-0.9.8/lib/facebook_web_session.rb:135:in `each’
E:/ruby/lib/ruby/gems/1.8/gems/rfacebook-0.9.8/lib/facebook_web_session.rb:135:in `photos_uploa
”
My code is as follows:
require “facebook_session”
module RFacebook
class FacebookWebSession auth_token})
unless result.nil?
@session_user_id = result.at(”uid”).inner_html
@session_key = result.at(”session_key”).inner_html
@session_expires = result.at(”expires”).inner_html
end
end
# Sets the session key directly (for example, if you have an infinite session)
#
# key:: the session key to use
def activate_with_previous_session(key, uid=nil, expires=nil)
# set the expiration
@session_expires = expires
# set the session key
@session_key = key
# determine the current user’s id
if uid
@session_user_id = uid
else
result = remote_call(”users.getLoggedInUser”)
@session_user_id = result.at(”users_getLoggedInUser_response”).inner_html
end
end
# returns true if this session is completely ready to be used and make API calls
def ready?
return (@session_key != nil and !expired?)
end
# Used for signing a set of parameters in the way that Facebook
# specifies:
#
# params:: a Hash containing the parameters to sign
def signature(params)
# always sign the parameters with the API secret
return signature_helper(params, @api_secret)
end
def photos_upload(params = {})
params = (params || {}).dup
params[:method] = “facebook.photos.upload”
params[:api_key] = FACEBOOK["key"]
params[:v] = API_VERSION
params[:session_key] = session_key
params[:call_id] = Time.now.to_f.to_s
file = params.delete :file
params[:sig] = signature(params)
boundary = ’some_long_and_random_string_which_wont_show_in_data_stream’
params_as_arr = []
p “on 31 line”
p params
params.each {|k,v|
p “<<<<<<<<<<<<<<<<”
p “text_to_multipart(k,v)”
p text_to_multipart(k,v)
params_as_arr << text_to_multipart(k,v)}
params_as_arr < “multipart/form-data; boundary=” + boundary).response.body.to_s
)
end
end
def text_to_multipart(key,value)
p “I aM IN”
p key
p value
return “Content-Disposition: form-data; name=\”#{key.to_s}\”\r\n” +
“\r\n” +
“#{value}\r\n”
end
def file_to_multipart(key,filename,mime_type,content)
return “Content-Disposition: form-data; name=\”#{key.to_s}\”; filename=\”#{CGI::escape(filename)}\”\r\n” +
“Content-Transfer-Encoding: binary\r\n” +
“Content-Type: #{mime_type}\r\n” +
“\r\n” +
“#{content}\r\n”
end
end
I am not able to understand what is happening?
Can you please tell me what is wrong?
Hi
I used this code and its working for me.
Thanks a lot.
I tried same code with minor changes for video but getting stuck with RemoteStandardError.
can any one know how to upload video through RFacebook.
Hi!
I’m glad You found this useful. However I do not work with facebook aps anymore and I can not help You with uploading video using RFacebook.