0.0
No release in over 3 years
Low commit activity in last 3 years
Lightway way to pull file from URL to tmp folder as a standard Ruby Tempfile
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.11
~> 10.0
~> 3.4
~> 3.0
~> 1.24
 Project Readme

PullTempfile

Build Status Code Climate

Simple way how to download file from url to temporary file. (Please read more on "why" would you need to do this down bellow)

Gem has no runtime gem dependancies (just standard Ruby lib) and it's really lightweight.

Installation

Add this line to your application's Gemfile:

gem 'pull_tempfile'

And then execute:

$ bundle

Or install it yourself as:

$ gem install pull_tempfile

Usage

Simplest example

require 'pull_tempfile'

original_filename = 'no idea.png'
url = 'https://meme.eq8.eu/noidea.jpg'

file = PullTempfile.pull_tempfile(url: url, original_filename: original_filename)
file.unlink # delete file after you done

# ...or

PullTempfile.transaction(url: url, original_filename: original_filename) do |tmp_file|
  puts tmp_file.path
  # ...
end

transaction will automatically delete (unlink) the temporary file after block finish.

Paperclip & Rails

require 'pull_tempfile'

class Medium < ActiveRecord::Base
  has_attached_file :file

  # ...
end

# when used as "AWS S3 browser upload" you can fetch original filename as "${filename}" metadata
# or use some different way to determine the file name.
original_filename = 'no idea.png'
url = 'https://meme.eq8.eu/noidea.jpg'

medium = Media.new

PullTempfile.transaction(url: url, original_filename: original_filename) do |tmp_file|
  medium.file = tmp_file
  medium.save!
end

Use HTTParty

PullTempfile.config.puller = ->(url){ HTTParty.get(url) }

License

The gem is available as open source under the terms of the MIT License.

Reason why this Gem exist:

This gem is trying to be usecase agnostic. For example you can use it to download CSV report and parse it and the CSV will automatically be deleted:

PullTempfile.transaction(url: 'https://mycompany.org/stupid-csv-report.csv', original_filename: 'dont-care.csv') do |tmp_file|
  CSV.foreach(tmp_file.path) do |row|
    # ....
  end
end

But main reason for it's existence is that when you using gem paperclip > 3.1.4 you can do something like this to pull file from url:

class User < ActiveRecord::Base
  attr_reader :avatar_remote_url
  has_attached_file :avatar

  def avatar_remote_url=(url_value)
    self.avatar = URI.parse(url_value)
    # Assuming url_value is http://example.com/photos/face.png
    # avatar_file_name == "face.png"
    # avatar_content_type == "image/png"
    @avatar_remote_url = url_value
  end
end

user = User.new
user.avatar_remote_url = 'http://example.com/photos/face.png'
user.save!

And this is how you upload file from url.

source https://github.com/thoughtbot/paperclip/wiki/Attachment-downloaded-from-a-URL

The problem is that if you do this on AWS S3 signd url is sending binary mime type binary/octet-stream and therefore if you are implementing validations on your uploads:

class User < ActiveRecord::Base
  # ...
  validates_attachment_content_type :avatar, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
  # ...
end

...you'll get error:

Validation failed: File has contents that are not what they are
reported to be, File is invalid, File content type is invalid

One solution is to skip validations in this context:

#...
medium.save!(validate: false)  # will skip validations

...but that's not secure.

Yes you can use context validations, or implement validations differently http://www.eq8.eu/blogs/22-different-ways-how-to-do-rails-validations but that's not the point,

So way how to get around this is to download the file to your /tmp/ folder as a temp file, and upload it via Paperclip

Install gem httparty

# Gemfile
# ...
gem 'httparty'
# ...

Run bundle install

Next create new file ./lib/s3_helper.rb

require 'httparty'      # gem
module S3Helper
  def pull_asset(url:, destination:)
    File.open(destination, "wb") do |f|
      f.binmode
      f.write HTTParty.get(url).parsed_response
      f.close
    end
  end
end

And now you can do something like:

user = User.new
require Rails.root.join('lib', 's3_helper')

S3Helper.pull_asset(url: "http://s3....../bbuesubeueueue", destination: "/tmp/my-file.jpg")

user.avatar = File.open("/tmp/my-file.jpg")
user.save!

But the problem is that you need to delete this file manually. So why not to take advantage of Ruby Tempfile. This is exactly what this gem is doing. Have a look on the Source code https://github.com/equivalent/pull_tempfile/blob/master/lib/pull_tempfile.rb