Storing image using open URI and paperclip having size less than 10kb
Solution 1
Try:
def icon_from_url(url)
extname = File.extname(url)
basename = File.basename(url, extname)
file = Tempfile.new([basename, extname])
file.binmode
open(URI.parse(url)) do |data|
file.write data.read
end
file.rewind
self.icon = file
end
Solution 2
To override the default filename of a "fake file upload" in Paperclip (stringio.txt
on small files or an almost random temporary name on larger files) you have 2 main possibilities:
Define an original_filename
on the IO:
def icon_from_url(url)
io = open(url)
io.original_filename = "foo.png"
self.icon = io
end
You can also get the filename from the URI:
io.original_filename = File.basename(URI.parse(url).path)
Or replace :basename
in your :path
:
has_attached_file :icon, :path => ":rails_root/public/:attachment/:id/:style/foo.png", :url => "/:attachment/:id/:style/foo.png"
Remember to alway change the :url
when you change the :path
, otherwise the icon.url
method will be wrong.
You can also define you own custom interpolations (e.g. :rails_root/public/:whatever
).
Solution 3
You are almost there I think, try opening parsed uri, not the string.
require "open-uri"
class Category < ActiveRecord::Base
has_attached_file :icon, :path =>:rails_root/public/:attachment/:id/:style/:basename.:extension"
def icon_from_url(url)
self.icon = open(URI.parse(url))
end
end
Of course this doesn't handle errors
Solution 4
You can also disable OpenURI from ever creating a StringIO object, and force it to create a temp file instead. See this SO answer:
Why does Ruby open-uri's open return a StringIO in my unit test, but a FileIO in my controller?
Mohit Jain
warning ! This is just a rip-off my linkedin profile :D Seasoned Web Developer with over 8 years of work experience, with focus on code quality, scaling, timely delivery, under pressure working experience and performance optimization. My responsibilities in the past ranged from designing and implementing large scalable systems, managing and monitoring clusters of servers, and also mentoring junior engineers and managing project teams. I'm always interested in hands-on contributions to challenging and innovative projects. Good interpersonal skills. Uncompromising work ethic and integrity. Known for quickly ramping up on new code bases and incorporating massive design changes in existing systems. Clean and efficient programming style. Excellent debugging practices, used to work in code written by different people. In the last few years, I wrote tens of thousands of lines of code to scale a system from 1 million users to 20 million users single-handedly. Specialities: Ruby on Rails, Redis, Memcache, MySQL, New Relic, Amazon Web Services, Over night prototyping, Mixpanel
Updated on June 14, 2022Comments
-
Mohit Jain almost 2 years
I want to import some icons from my old site. The size of those icons is less than 10kb. So when I am trying to import the icons its returning stringio.txt file.
require "open-uri" class Category < ActiveRecord::Base has_attached_file :icon, :path => ":rails_root/public/:attachment/:id/:style/:basename.:extension" def icon_from_url(url) self.icon = open(url) end end
In rake task.
category = Category.new category.icon_from_url "https://xyz.com/images/dog.png" category.save
-
Mohit Jain almost 13 yearsthis code worked for the first image but then nothing. I have a loop of some 350 images. I double checked the links. its perfectly fine. In addition image name is not the same.
-
Kevin Sylvestre almost 13 years@Mohit Are you calling
save
on your model after performing this method? -
Michaël Witrant almost 13 yearsSetting
original_filename
on the IO returned by open-uri is much simpler and faster. -
Dustin M. about 12 yearsI am trying to use this but if I try to set original_filename on io in this example I am getting an NoMethodError: undefined method `original_filename=' Error on the tempfile. Ruby 1.8.7 rails 2.3.8
-
Matstar over 11 years@DustinM. This works:
def io.original_filename; "foo.png"; end
-
Paul Brannan over 11 yearsI can confirm that this works. In order to access a local variable, I had to use define_method: open(doc.url) do |file| file.singleton_class.instance_eval do define_method(:original_filename) { doc.title } end end
-
Nadeem Yasin over 10 yearsIts not going to save extenstion!
-
mpoisot over 10 years@MichaëlWitrant I found that PaperClip 3.5.1 performs MIME type validations based on the Tempfile's filename. It doesn't matter if
original_filename
is set. I used @KevinSylvestre's method to force the Tempfile to have the correct extension, and thus PaperClip "guessed" the correct MIME type. (You could argue that the validation is useless in this scenario, but having the correct MIME type stored in the DB might be useful.) -
Joshua Plicque about 8 yearsThis doesn't work due to the undefined method error.