Pages

Thursday, January 30, 2014

API Upload with CarrierWave

 I want to share a quick snippet with regards to a problem I had a few months ago: How to upload a picture/file to a Ruby on Rails project, which is utilizing CarrierWave to handle the upload mechanism, by utilizing the direct POST call.
With this comes at least two challenges:
  • You cannot insert a file directly into a JSON object;
  • CarrierWave does not support uploading a file which is not uploaded using a form object.
Solving the first problem is almost trivial, you simply encode the file into Base64 and pass it along, but the second problem requires a little more work. What I did to solve it was to decode the Base64 string into a temp file, and then create a new uploaded file from that temp file.
# POST /pictures
   # POST /pictures.json
   def create
     #check if file is within picture_path
     if params[:picture][:picture_path]["file"]
          picture_path_params = params[:picture][:picture_path]
          #create a new tempfile named fileupload
          tempfile = Tempfile.new("fileupload")
          tempfile.binmode
          #get the file and decode it with base64 then write it to the tempfile
          tempfile.write(Base64.decode64(picture_path_params["file"]))
          #create a new uploaded file
          uploaded_file = ActionDispatch::Http::UploadedFile.new(:tempfile => tempfile, :filename => picture_path_params["filename"], :original_filename => picture_path_params["original_filename"])
          #replace picture_path with the new uploaded file
          params[:picture][:picture_path] =  uploaded_file
     end
     @picture = Picture.new(params[:picture])
     respond_to do |format|
       if @picture.save
         format.html { redirect_to @picture, notice: 'Picture was successfully created.' }
         format.json { render json: @picture, status: :created, location: @picture }
       else
         format.html { render action: "new" }
         format.json { render json: @picture.errors, status: :unprocessable_entity }
       end
     end
   end


The code above is fairly self explanatory, so I wont bother to go through it again, but it is critical to know what the structure of my json call looked like:

picture {:user_id => "1", :folder_id => 1, etc., :picture_path {:file => "base64 awesomeness", :original_filename => "my file name", :filename => "my file name"}}


Finally, you will need to delete the temp file in some way, but I’ll leave that up to you.
Happy coding!

No comments:

Post a Comment