Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to save a raw_data photo using paperclip

I'm using jpegcam to allow a user to take a webcam photo to set as their profile photo. This library ends up posting the raw data to the sever which I get in my rails controller like so:

def ajax_photo_upload
  # Rails.logger.info request.raw_post
  @user = User.find(current_user.id)
  @user.picture = File.new(request.raw_post)

This does not work and paperclip/rails fails when you try to save request.raw_post.

Errno::ENOENT (No such file or directory - ????JFIF???

I've seen solutions that make a temporary file but I'd be curious to know if there is a way to get Paperclip to automatically save the request.raw_post w/o having to make a tempfile. Any elegant ideas or solutions out there?

UGLY SOLUTION (Requires a temp file)

class ApiV1::UsersController < ApiV1::APIController

  def create
    File.open(upload_path, 'w:ASCII-8BIT') do |f|
      f.write request.raw_post
    end
    current_user.photo = File.open(upload_path)
  end

 private

  def upload_path # is used in upload and create
    file_name = 'temp.jpg'
    File.join(::Rails.root.to_s, 'public', 'temp', file_name)
  end

end

This is ugly as it requires a temporary file to be saved on the server. Tips on how to make this happen w/o the temporary file needing to be saved? Can StringIO be used?

like image 794
AnApprentice Avatar asked Oct 09 '12 01:10

AnApprentice


1 Answers

The problem with my previous solution was that the temp file was already closed and therefore could not be used by Paperclip anymore. The solution below works for me. It's IMO the cleanest way and (as per documentation) ensures your tempfiles are deleted after use.

Add the following method to your User model:

def set_picture(data)
  temp_file = Tempfile.new(['temp', '.jpg'], :encoding => 'ascii-8bit')

  begin
    temp_file.write(data)
    self.picture = temp_file # assumes has_attached_file :picture
  ensure
    temp_file.close
    temp_file.unlink
  end
end

Controller:

current_user.set_picture(request.raw_post)
current_user.save

Don't forget to add require 'tempfile' at the top of your User model file.

like image 84
Mischa Avatar answered Nov 15 '22 01:11

Mischa