Storing image using open URI and paperclip having size less than 10kb

巧了我就是萌 提交于 2019-12-05 00:49:08

问题


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

回答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



回答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).




回答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




回答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?




回答5:


In the past, I found the most reliable way to retrieve remote files was by using the command line tool "wget". The following code is mostly copied straight from an existing production (Rails 2.x) app with a few tweaks to fit with your code examples:

class CategoryIconImporter
  def self.download_to_tempfile (url)
    system(wget_download_command_for(url))
    @@tempfile.path
  end

  def self.clear_tempfile
    @@tempfile.delete if @@tempfile && @@tempfile.path && File.exist?(@@tempfile.path)
    @@tempfile = nil
  end

  def self.set_wget
    # used for retrieval in NrlImage (and in future from other sies?)
    if !@@wget
      stdin, stdout, stderr = Open3.popen3('which wget')
      @@wget = stdout.gets
      @@wget ||= '/usr/local/bin/wget'
      @@wget.strip!
    end
  end
  def self.wget_download_command_for (url)
    set_wget
    @@tempfile = Tempfile.new url.sub(/\?.+$/, '').split(/[\/\\]/).last
    command = [ @@wget ]
    command << '-q'
    if url =~ /^https/
      command << '--secure-protocol=auto'
      command << '--no-check-certificate'
    end
    command << '-O'
    command << @@tempfile.path
    command << url
    command.join(' ')
  end

  def self.import_from_url (category_params, url)
    clear_tempfile

    filename = url.sub(/\?.+$/, '').split(/[\/\\]/).last
    found = MIME::Types.type_for(filename)
    content_type = !found.empty? ? found.first.content_type : nil

    download_to_tempfile url

    nicer_path = RAILS_ROOT + '/tmp/' + filename
    File.copy @@tempfile.path, nicer_path

    Category.create(category_params.merge({:icon => ActionController::TestUploadedFile.new(nicer_path, content_type, true)}))
  end
end

The rake task logic might look like:

[
  ['Cat', 'cat'],
  ['Dog', 'dog'],
].each do |name, icon|
  CategoryIconImporter.import_from_url {:name => name}, "https://xyz.com/images/#{icon}.png"
end

This uses the mime-types gem for content type discovery:

gem 'mime-types', :require => 'mime/types'


来源:https://stackoverflow.com/questions/6291733/storing-image-using-open-uri-and-paperclip-having-size-less-than-10kb

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!