Search code examples
iosimagerubymotion

RubyMotion uploading image from iOS to Rails/S3 using Formotion and BubbleWrap


In my Rails app I use Paperclip to upload photos and store them in S3. So I wanted to bring that functionality into my iOS app. I got image uploading to work in my RubyMotion app using this gist, but it was incredibly slow. After seeing this dated issue in Paperclip, I tried a different approach: https://github.com/thoughtbot/paperclip/issues/254#issuecomment-321507.

So I tried using BubbleWrap's :form_data :format and passing UIImage.UIImageJPEGRepresentation(@form.render[:photo], 1) instead to see if that would speed things up. However it isn't working. It seems like whatever photo is selected isn't actually getting rendered properly, because I'm not seeing any photo params in my server. And the output of UIImage.UIImageJPEGRepresentation(@form.render[:photo], 1) doesn't look right.

My Formotion form:

@form = Formotion::Form.new({
  title: "Settings",
  sections: [{
    title: "Personal Information",
    rows: [{
      title: "Photo",
      type: :image,
      key: :photo,
      value: @profile_photo
    }, {
      title: "Name",
      type: :string,
      placeholder: "Name",
      key: :name,
      value: @profile['name']
    }]
  }]
})

My BubbleWrap PUT to update the profile:

profile_photo = UIImage.UIImageJPEGRepresentation(@form.render[:photo], 1)

data = {
  'profile[name]'    => @form.render[:name],
  'profile[photo]'   => profile_photo,
  'user[api_token]'  => CONFIG.user.api_token,
  _method:              'PUT'
}

BW::HTTP.post("#{DEFAULT_URL}/profiles/#{CONFIG.user.profile_id}", { format: :form_data, payload: data }) do |response|
  parsed_response = BW::JSON.parse(response.body.to_str)
  if response.ok?
    @data = parsed_response
    self.dismissViewControllerAnimated(true, completion:lambda { parent.load_profile() })
  else
    App.alert("#{parsed_response.first}")
  end
end

So my question is: Must I encode the image like the gist suggests with .pack("m0")? Is there a way to speed up this process at all with all the binary data I'm passing to my server?


Solution

  • I have no idea to do such a thing with BubbleWrap but ...

    .. here is an example to upload files with AFMotion(which is a wrapper around AFNetworking).

    client = AFMotion::Client.build("your endpoint") do
      header "Accept", "application/json"
      operation :json
    end
    
    image = my_function.get_image
    data = UIImagePNGRepresentation(image)
    
    client.multipart.post("avatars") do |result, form_data|
      if form_data
        # Called before request runs
        # see: https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-FAQ
        form_data.appendPartWithFileData(data, name: "avatar", fileName:"avatar.png", mimeType: "image/png")
      elsif result.success?
        ...
      else
        ...
      end
    end
    

    You might want to take a look at the documentation/example of AFMotion here

    Hope it helps.