Please suggest me a way to save an image from an URL by Paperclip.
8 Answers
In Paperclip 3.1.4 it's become even simpler.
def picture_from_url(url)
self.picture = URI.parse(url)
end
This is slightly better than open(url). Because with open(url) you're going to get "stringio.txt" as the filename. With the above you're going to get a proper name of the file based on the URL. i.e.
self.picture = URI.parse("http://something.com/blah/avatar.png")
self.picture_file_name # => "avatar.png"
self.picture_content_type # => "image/png"

- 45,245
- 23
- 243
- 245

- 13,370
- 2
- 44
- 50
-
3From paperclip wiki: https://github.com/thoughtbot/paperclip/wiki/Attachment-downloaded-from-a-URL I successfully run it in console, the app is in heroku. – Donny Kurnia Jan 17 '13 at 23:52
-
3FYI, for S3 urls I still get `application/octet_stream` as the `content_type`. – Joshua Pinter Jan 06 '15 at 15:46
-
7If you are still using paperclip after it's deprecation, you may need to also ensure the URI IO loader gets loaded: Paperclip::UriAdapter.register (in the config, or temporarily via the console if that's all you need) – Msencenb Nov 09 '18 at 14:56
-
The approach is correct but in last version the sintax is changed! Check out my answer below => https://stackoverflow.com/a/56039191/3182171 – Diego D May 08 '19 at 11:01
-
1You need to add entry in initializer https://github.com/thoughtbot/paperclip/wiki/Attachment-downloaded-from-a-URL – ianpetzer Aug 20 '19 at 15:52
Here is a simple way:
require "open-uri"
class User < ActiveRecord::Base
has_attached_file :picture
def picture_from_url(url)
self.picture = open(url)
end
end
Then simply :
user.picture_from_url "http://www.google.com/images/logos/ps_logo2.png"

- 11,164
- 7
- 38
- 49
-
7If you need to use `update_attributes` rename `picture_from_url` to `picture_url=(value)` for example. – Daniel Rikowski Jun 02 '13 at 13:07
-
4This is potentially insecure because a user could call `user.picture_from_url('/etc/password')`. It's probably fine in most situations though. – David Tuite Oct 11 '13 at 09:16
-
1For security, you should whitelist the URI's scheme and blacklist private hosts – John Douthat Jan 07 '14 at 17:56
-
3
-
6Using `open(url)`, the filename is not accurate, e.g. `open-uri20150106-10034-lpd5fm.` instead of `ef3a601e_ef3d008b_ef3d0f7e.jpg`. – Joshua Pinter Jan 06 '15 at 15:48
-
It didn't work for me until I used "open" for parsed URI. once I added "open" it worked!
def picture_from_url(url)
self.picture = URI.parse(url).open
end
My paperclip version is 4.2.1
Before open it wouldn't detect the content type right, because it wasn't a file. It would say image_content_type: "binary/octet-stream", and even if I override it with the right content type it wouldn't work.

- 1,085
- 12
- 21
-
-
You will lose your exension if you do this. You need Paperclip::UriAdapter.register in the initializer.. then you don't need .open at the end. See https://github.com/thoughtbot/paperclip/wiki/Attachment-downloaded-from-a-URL – ianpetzer Aug 20 '19 at 15:52
First download the image with the curb
gem to a TempFile
and then simply assign the tempfile object and save your model.

- 10,910
- 6
- 43
- 40
-
2I don't see what's wrong with this answer, voting it up 'cause I'm seeing a down vote. – jpemberthy Aug 10 '11 at 21:50
-
This is the most performant answer ([by far](http://toevolve.org/2011/04/03/http-request-performance.html)). I am not really a performance-geek, but this really adds up if you are working w/ large files. – Chip Sep 23 '13 at 23:50
Into official documentation is reported here https://github.com/thoughtbot/paperclip/wiki/Attachment-downloaded-from-a-URL
Anyway it seems not updated, because in last version of paperclip something has changed and this line of code is no more valid:
user.picture = URI.parse(url)
It raise an error, in particular this error is raised:
Paperclip::AdapterRegistry::NoHandlerError: No handler found for #<URI:: ...
The new correct syntax is this one:
url = "https://www.example.com/photo.jpeg"
user.picture = Paperclip.io_adapters.for(URI.parse(url).to_s, { hash_digest: Digest::MD5 })
Also we need to add these lines into config/initializers/paperclip.rb file:
Paperclip::DataUriAdapter.register
Paperclip::HttpUrlProxyAdapter.register
Tested this with paperclip version 5.3.0
and it works.

- 1,706
- 19
- 23
As those are old Answer's here's a newer one:
Add Image Remote URL to your desired Controller in the Database
$ rails generate migration AddImageRemoteUrlToYour_Controller image_remote_url:string
$ rake db:migrate
Edit your Model
attr_accessible :description, :image, :image_remote_url
.
.
.
def image_remote_url=(url_value)
self.image = URI.parse(url_value) unless url_value.blank?
super
end
*In Rails4 you have to add the attr_accessible in the Controller.
Update your form, if you allow other to upload an Image from a URL
<%= f.input :image_remote_url, label: "Enter a URL" %>

- 7,855
- 9
- 59
- 108
-
-
The function `super` is used to invoke the original method, searching of the method body starts in the super class of the object that was found to contain the original method – Mini John Aug 27 '14 at 06:35
It may helpful to you. Here is the code using paperclip and image present in remote URL .
require 'rubygems'
require 'open-uri'
require 'paperclip'
model.update_attribute(:photo,open(website_vehicle.image_url))
In model
class Model < ActiveRecord::Base
has_attached_file :photo, :styles => { :small => "150x150>", :thumb => "75x75>" }
end

- 6,121
- 8
- 35
- 39
This is a hardcore method:
original_url = url.gsub(/\?.*$/, '')
filename = original_url.gsub(/^.*\//, '')
extension = File.extname(filename)
temp_images = Magick::Image.from_blob open(url).read
temp_images[0].write(url = "/tmp/#{Uuid.uuid}#{extension}")
self.file = File.open(url)
where Uuid.uuid just makes some random ID.

- 1,983
- 1
- 18
- 18