where from does paperclip get the name of original file? - ruby-on-rails

i started using nginx upload module (which creates upload files like /tmp/000121545) but i need paperclip to use original filename while saving files (like /public/avatars/LuckyLuke.jpg)
previously in the parameters Rails were passing just
"avatar"=>#<File:/tmp/RackMultipart20100413-6151-t3ecq0-0>
no original filename as well, so i am wondering where from does it come in paperclip? i tried looking through plugin code but it's currently a bit too complex for me.

The browser sends a http header with the file name. ("Content-Disposition: filename=original_file.jpg")
Rails makes this available as a instance method of the temp file object: params[:avatar].original_filename, and paperclip uses that.
In detail, Rack parses the multipart form in Rack::Utils::Multipart::UploadedFile and puts a hash in the parameters that includes :tempfile and :filename. Then ActionDispatch::Http::Upload comes along and replaces that hash by the File object (value of :tempfile), extending it with the module ActionDispatch::Http::UploadedFile, which adds a instance variable for original_path and the method original_filename.

Related

Encode Carrierwave attachment to base64 in Rails

I am using the Carrierwave gem to upload attachments to my model. I added elasticsearch with the mapper attachments plugin to allow for full text search of the attachments.
Carrierwave and elasticsearch work fine, but in order to get the full text search working I need to encode the attachment as base64.
I have followed this tutorial (http://rny.io/rails/elasticsearch/2013/08/05/full-text-search-for-attachments-with-rails-and-elasticsearch.html) but I assume there has been some changes to either Rails or Carrierwave as I can't get it to work. Specifically, when I am trying to encode the attachment as base64, I get the following Type error:
no implicit conversion of CarrierWave::SanitizedFile into String
The error is in the following line of the model:
File.open(Base64.encode64(File.read(document.file)))
If I replace the path with a url to an actual file it works fine.
I have searched SO and the only relevant answer I can find gives me the same error: Carrierwave encode file to base64 as process
I am a complete rails newbie and hopefully this is something that's obvious to everyone except me, but we're all beginners at first, right?
Thanks!
CarrierWave's read method returns the content of the file. So assuming Document is your model and file is your uploader attribute, this should work:
Base64.encode64(document.file.read)

How can I identify the kind of file in rackspace?

I gonna upload files to rackspace(video, audio and images) in rails with paperclip or carrierwave, I need to Know the kind of file, to show in the view with image_tag, or video_tag or audio_tag, rackspace tell me the kind of file? or I have to store in my database? thanks
You can query/set the file type by using the 'content_type' function located in the 'ruby-cloudfiles' library.
See here: https://github.com/rackerlabs/ruby-cloudfiles/blob/master/lib/cloudfiles/storage_object.rb#L80-L82
Something like this should work for creating the object:
container = conn.create_container('new_container')
obj = container.create_object('new_obj.txt')
obj.load_from_filename('./obj.txt')
obj.content_type = 'text/plain'
And to retrieve the object:
obj = container.object('new_obj.txt')
puts obj.content_type # text/plain
Even if rackspace would tell you the file type, you don't want it to, since it would take so long to run roundtrips from your server to theirs.
My code examples below assume carrierwave, but I'm sure paperclip has similar options. Two options:
Interpret the file extension
Something like: File.extname(user.avatar), which you then have to interpret however you like.
Record & interpret the mime type.
The carrierwave readme explains how to get carrierwave to calculate it in the first place, and then you should probably store it to your database manually or using carrierwave-meta. Then user.avatar.content_type would be something like image/jpeg which you could easily interpret as a particular file type.

Paperclip Rails url and asset_host

According to the Paperclip S3 Docs one can specify the :url option in the config which has four possible values. There are comments related to this options that say:
The fourth option for the S3 url is :asset_host, which uses Rails' built-in asset_host settings.
To get the full url from a paperclip'd object, use the image_path helper; this is what image_tag uses to generate the url for an img tag.
These two comments seem in conflict with each other (to me). If Paperclip can use the asset_host settings, it seems almost necessary that it would generate the full url (since the asset_host only specifies the start (host) of that url)
But it then goes on to say you need to use a helper to get the full url??
The reason I ask this is because I want full urls generated for image url serialization (ie if we're returning json with image_urls, we want those served from our CDN).
Right now I've created a helper module that extends extend ::Sprockets::Helpers::RailsHelper to manually generate full urls any time an image_url is being serialized, but it's manual (and someone could possibly forget to do it in the future)
Any thoughts?

Accessing an uploaded file without actually storing it in the database or on the server -- Ruby on Rails

I have a system where the user uploads a file and I have to read the file and display its contents on a form without storing it either on the server side or in the database
When the file is uploaded Rails will automatically read it in and make it an instance of Tempfile so it's already stored, it won't however be stored forever on the system.
You can access the file using the normal params[:field_name] syntax as if the file were any other field (don't forget to set content-type of the form to multipart/form-data - i.e.
form_for #mything, :html => {:multipart => true})
and you will get back the tempfile. The tempfile can be read from like any other file.
Rails (Or Maybe Rack I'm not 100% up to date) determines whether to do this or not to uploaded content based on the attachment part of the mulitpart/form-data element containing the file.
It might be possible to override things if you need to though to stop this storage from happening. Common practice however is to just work with the file and then let Ruby deal with the temp file.

Using restclient with multipart posts

I'm using restclient for a multipart form to send data to a restful web service (it's Panda video encoding service).
The trick though, is that the file I am passing into restclient (Technoweenie branch) is coming from my own form that a user submits.
So, lets walk through this. A user posts a file to my rails app. In my controller, it receives the file from params[:file]. I then want to pass params[:file] down to Panda using RestClient.
The error I'm getting is on the Panda server follows. I noticed that the file param in the stack trace is in a string as well (which I assume is Panda turning into a string for a nicer stacktrace).
~ Started request handling: Wed Aug 12 18:05:15 +0000 2009
~ Params: {"format"=>"html", "multipart"=>"true", "account_key"=>"SECURE_KEY", "action"=>"upload", "id"=>"SECURE_ID", "controller"=>"videos", "file"=>"#<File:0xcf02ca4>"}
~ 9bfb1750-6998-012c-4509-12313900b0f6: (500 returned to client) InternalServerErrorcan't convert nil into String
/var/local/www/panda/app/models/video.rb:246:in `extname'
/var/local/www/panda/app/models/video.rb:246:in `initial_processing'
/var/local/www/panda/app/controllers/videos.rb:79:in `upload'
I doubt you can really pass a CGI-style upload param from Rails into restclient and expect it to work.
A regular upload in Rails would have quite some extra attributes which do not belong in a posted resource (like the original filename and so on), and a Rails upload contains an IO with the actual file data. Also a file upload object in Rails might be a Tempfile handle and might be a StringIO - depending on the size of the upload.
What you effectively need to do is "repackage" your upload for rest-client to handle it properly, and pass the repackaged and rewound Tempfile object to restclient. Maybe you can get away with just picking the upload object itself instead of the whole params[:file]
Confirm that your restclient action can save locally first. If the action cannot save locally, then you will have a better idea where to look while trouble shooting.
Looks like the problem is with rest-client's posting of the file, check out an alternative method for posting like curb.
Lots of examples for posting multipart form data on this question: Ruby: How to post a file via HTTP as multipart/form-data?

Resources