4

我正在使用OmniAuth为我的用户收集Oauth/OAuth2凭据,然后以他们的名义发布到这些服务的Rails应用程序。Ruby on Rails - OAuth 2多部分发布(上传至Facebook或Soundcloud)

创建简单的帖子来更新状态饲料工作很好..现在我需要上传文件。 Facebook说:“要发布照片,请发送带有照片文件附件的POST请求作为multipart/form-data。” http://developers.facebook.com/docs/reference/api/photo/

所以这是我想做的事:

我已经实现了这里的模块:Ruby: How to post a file via HTTP as multipart/form-data?获得头和数据...

if appearance.post.post_attachment_content_type.to_s.include?('image') 

    fbpost = "https://graph.facebook.com/me/photos" 

    data, headers = Multipart::Post.prepare_query("title" => appearance.post.post_attachment_file_name , "document" => File.read(appearance.post.post_attachment.path)) 

    paramsarray = {:source=>data, :message=> appearance.post.content} 
    response = access_token.request(:post, fbpost, paramsarray, headers) 
    appearance.result = response 
    appearance.save 
end 

我,但我得到一个的OAuth2 :: HTTPError - HTTP 400错误

任何帮助将是令人难以置信的...正如我看到这些信息也将需要上传文件到SoundCloud也。

感谢,

马克

回答

2

自己挣扎与此有关。 oauth2库由法拉第支持,因为它是HTTP交互。有一点点配置,它支持开箱即用的上传文件。第一步是在建立连接时添加适当的法拉第中间件。我的代码示例如下:

OAuth2::Client.new client_id, secret, site: site do |stack| 
    stack.request :multipart 
    stack.request :url_encoded 
    stack.adapter Faraday.default_adapter 
end 

这会将多部分编码支持添加到法拉第连接。接下来,在访问令牌对象上发出请求时,您要使用Faraday :: UploadIO对象。所以:

upload = Faraday::UploadIO.new io, mime_type, filename 
access_token.post('some/url', params: {url: 'params'}, body: {file: upload}) 

在上面的代码:

IO - 你要上传的文件的IO对象。可以是文件对象或甚至是StringIO。

mime_type - 您正在上传的文件的MIME类型。您可以尝试检测此服务器端,或者如果用户将文件上传到您,您应该能够从他们的请求中提取MIME类型。

filename - 什么是调用您正在上传的文件。这也可以由您自己选择确定,或者您可以使用上传文件的用户调用它。

一些/ URL - 你要张贴到

网址替换此

网址:{url: 'PARAMS'} - 参数数量要提供的任何URL替换此

{文件:上传} - 用您的多部分表单数据替换。显然,一个(或多个)键/值对应该有一个文件上传的实例。

0

我实际使用成功后,该代码上传FB页面上的照片:

dir = Dir.pwd.concat("/public/system/posts/images") 
fb_url = URI.parse("https://graph.facebook.com/#{@page_id}/photos") 
img = File.open("myfile.jpg") 
req = Net::HTTP::Post::Multipart.new(
    "#{fb_url.path}?access_token=#{@token}", 
    "source" => UploadIO.new(img, "application/jpg", img.path), 
    "message" => "some messsage" 
) 
n = Net::HTTP.new(fb_url.host, fb_url.port) 
n.use_ssl = true 
n.verify_mode = OpenSSL::SSL::VERIFY_NONE 
n.start do |http| 
    @result = http.request(req) 
end