Restful File Uploads with Carrierwave

RESTful file uploads with CarrierWave

CarrierWave also accepts a StringIO, but it expects a original_filename method, since it needs it for figuring out the file name and doing the extension check. How you do it changed between Rails 2 and 3, here's both methods:

Rails 2

io = StringIO.new(Base64.decode64(encoded_img))
io.original_filename = "foobar.png"

p.image_file = io
p.save

In Rails 3, you need to make a new class and then manually add original_filename back

class FilelessIO < StringIO
attr_accessor :original_filename
end

io = FilelessIO.new(Base64.decode64(encoded_img))
io.original_filename = "foobar.png"

p.image_file = io
p.save

Upload file with api and carrierwave

Basically it is based on the tool which is used by the API consumer. If API consumer is using ruby then can consume it by passing File object, or using httmultiparty gem we can upload the file.

For you reference https://github.com/jwagener/httmultiparty. Please let me know if you need more help.

How do I upload a file via Carrierwave over a JSON API?

When an HTML form POSTs a file, what actually happens is a special part of HTTP called a multipart request. Effectively, the file gets "attached" to the request.

The question will be answered by what library you are using to POST the JSON to your api. Attaching a file to a request should be fairly commonplace but not all libraries may support it.

This stack overflow article seems to give some good indications of how to do it.

Carrierwave testing - clean up or separate file uploads?

The location where the files are stored is defined in a Carrierwave Uploader by the method store_dir. If you need to separate the files created in different environments, the simplest solution is to add Rails.env to the path:

def store_dir
@store_dir ||= File.join(
'public',
'uploads',
Rails.env,
model.class.table_name.to_s,
mounted_as.to_s,
model.id.to_s
)
end

This will create a path like: public/uploads/production/posts/image/1/image.png

carrierwave multiple file uploads and storing

Add the relevant attributes to your model and introduce a before_save callback.

class Video < ActiveRecord::Base
mount_uploader :video, VideoUploader

before_save :update_video_attributes
private

def update_video_attributes
if video.present? && video_changed?
self.content_type = video.file.content_type
self.file_size = video.file.size
end
end
end

For more details see github

Uploading a raw file to Rails using Carrierwave

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.

Carrierwave - uploading a file from a string

Your solution of using File.open would work, but you should verify that the name is valid with File.basename so someone couldn't pass ../../secret_credentials.yml and expose info you don't want them to. Also checking it against the list of preset images would be a good idea.

However, you can do this more efficiently by skipping CarrierWave in this case.

Add a new field called library_image, when someone wants to use a preset image, then you set library_image, if they want to use their own photo, unset library_image and upload the photo as normal. Then add a helper method like:

def avatar_url
if self.library_image?
"http://example.com/images/#{self.library_image}"
else
self.picture.url
end
end

This assumes that you can find the preset images at http://example.com/images/[name] and you are using mount_uploader in CarrierWave named picture.

Now anytime you want to display their picture, you would call avatar_url which will check if it should return the preset URL, or the picture they uploaded.

An example of how you would update library_image or picture based on your original question:

if params[:file].is_a?(Hash)
model.library_image = params[:file][:url]
model.remove_picture = true
else
model.library_image = nil
model.picture = params[:file]
end


Related Topics



Leave a reply



Submit