Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Make a remote URL work like a file upload (in Rails) (See related posts)

Want to load a remote URL into an acts_as_attachment/attachment_fu model? Use this little utility class.

  class UrlUpload
    EXTENSIONS = {
      "image/jpeg" => ["jpg", "jpeg", "jpe"],
      "image/gif" => ["gif"],
      "image/png" => ["png"]
    }
    attr_reader :original_filename, :attachment_data
    def initialize(url)
      @attachment_data = open(url)
      @original_filename = determine_filename
    end

    # Pass things like size, content_type, path on to the downloaded file
    def method_missing(symbol, *args)
      if self.attachment_data.respond_to? symbol
        self.attachment_data.send symbol, *args
      else
        super
      end
    end
    
    private
      def determine_filename
        # Grab the path - even though it could be a script and not an actual file
        path = self.attachment_data.base_uri.path
        # Get the filename from the path, make it lowercase to handle those
        # crazy Win32 servers with all-caps extensions
        filename = File.basename(path).downcase
        # If the file extension doesn't match the content type, add it to the end, changing any existing .'s to _
        filename = [filename.gsub(/\./, "_"), EXTENSIONS[self.content_type].first].join(".") unless EXTENSIONS[self.content_type].any? {|ext| filename.ends_with?("." + ext) }
        # Return the result
        filename
      end
  end


Now when you have the URL you want to load, do something like this:

@model.uploaded_data = UrlUpload.new(url)


Or better yet, make a pseudo-accessor on your aaa/attachment_fu model so you can stay "model-heavy".

def url=(value)
  self.uploaded_data = UrlUpload.new(value)
end

Comments on this post

seancribbs posts on May 26, 2007 at 14:43
One additional thing I had to do to make it fail-safe is open up the open-uri library and set it to always use Tempfile downloads, rather than StringIO. Here's a monkey-patch for it:

# Make it always write to tempfiles, never StringIO
OpenURI::Buffer.module_eval {
  remove_const :StringMax
  const_set :StringMax, 0
}
klintan posts on Jul 31, 2007 at 10:11
How do i use this script? It doesn´t seem to work. Do I need to include OpenURI or something?
supagroova posts on Nov 20, 2007 at 04:23
Yes you need to include the OpenURI library. Use this:

require 'open-uri'

exlibris posts on Dec 16, 2007 at 15:46
@seanscribbs
Where in open-uri.rb do I put that snippet?

You need to create an account or log in to post comments to this site.


Click here to browse all 4863 code snippets

Related Posts