Uploading a raw file to Rails using Carrierwave

jevy picture jevy · Jun 20, 2011 · Viewed 8.8k times · Source

My clients are trying to upload an image from Blackberry and Android phones. They don't like posting a)form parameters or b) multipart messages. What they would like to do is do a POST to a url with only the data from the file.

Something like this can be done in curl: curl -d @google.png http://server/postcards/1/photo.json -X POST

I'd like the uploaded photo to put into the photo attribute of the postcards model and into the right directory.

I'm doing something like this in the controller but the image is corrupted in the directory. I am doing a manual renaming of the file to a "png" for now:

def PostcardsController < ApplicationController
...
# Other RESTful methods
...
def photo
  @postcard = Postcard.find(params[:id])
  @postcard.photo = request.body
  @postcard.save
end

The model:

class Postcard < ActiveRecord::Base
  mount_uploader :photo, PhotoUploader
end

Answer

Samuel picture Samuel · Jun 20, 2011

This can be done but you will still need your clients to send the orignal filename (and the content-type if you do any validation on the type).

def photo
  tempfile = Tempfile.new("photoupload")
  tempfile.binmode
  tempfile << request.body.read
  tempfile.rewind

  photo_params = params.slice(:filename, :type, :head).merge(:tempfile => tempfile)
  photo = ActionDispatch::Http::UploadedFile.new(photo_params)

  @postcard = Postcard.find(params[:id])
  @postcard.photo = photo

  respond_to do |format|
    if @postcard.save
      format.json { head :ok }
    else
      format.json { render :json => @postcard.errors, :status => :unprocessable_entity }
    end
  end
end

And now you can set the photo using

curl http://server/postcards/1/photo.json?filename=foo.png --data-binary @foo.png

And to specify the content-type use &type=image/png.