3

I'm using Rails 4, Ruby 2.0, Paperclip 3.5.2. My production.rb has the following

  config.paperclip_defaults = {
  :storage => :s3,
  :s3_credentials => {
  :bucket => ENV['S3_BUCKET_NAME'],
  :access_key_id => ENV['AWS_ACCESS_KEY_ID'],
  :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
  }
  }

I can save files and I can retrieve the files in the view.html.erb with

  `<%= image_tag card.ai.url(:thumb) %>`

My question is, how can I access the file in the controller? I would like to add it to a zip file, z:

def create_zip
....
elsif ENV['RAILS_ENV'] == "production"
        z.add_file(card.ai.path)
...
end

This gives the error: "Can't open file: No such file or directory". Also tried "card.ai.url.path"- of course that didn't work. I've read [Paperclip + S3 massive zipping, but no I don't want to disable anything. So basically there's a lot of posts that say how to show the image file in the .html.erb file, but I want to access it in the controller.

-so close to finishing

Have gotten this far...it doesn't crash the website and temp_file does go into the zip file, but temp_file is empty.

        s3One = AWS::S3.new(:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
                         :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'])
        cardsets_bucket = s3One.buckets[ENV['S3_BUCKET_NAME']]
        ai_file_object = cardsets_bucket.objects[card.ai]

        temp_dir_name = "#{Rails.root}/public/temp/pictures}"
        temp_dir = File.dirname("#{temp_dir_name}")
        unless File.directory?("#{temp_dir_name}")
          FileUtils.mkdir_p("#{temp_dir_name}")
        end
        if File.exists?("#{temp_dir_name}/tempPicture.jpg")
          File.delete("#{temp_dir_name}/tempPicture.jpg")
        end
        temp_file = File.new("#{temp_dir_name}/tempPicture.jpg", 'w')

        File.open("#{temp_dir_name}/tempPicture.jpg", 'w') do |file|
          ai_file_object.read do |chunk|
          file.write(chunk)
          end
        end
        z.add_file("#{temp_dir_name}/tempPicture.jpg")

Have also tried ai_file_object = cardsets_bucket.objects[card.ai.url] --still tempPicture is empty. Also tried card.ai.path and results in error AWS can not find key.

Thanks in advance.

flobacca
  • 936
  • 2
  • 17
  • 42

2 Answers2

2

I needed to find out what the file path was in S3 and use "wb" when downloading. I looked inside my development public/system/cards folder to see how paperclip names their files. It is TABLENAME/ATTACHED_FILE/000/000/CARD.ID/original. (Notice tablename and attached_file are plural and 'original' could be replaced with 'thumb'.) I also put this into a view <%= card.ai.path %>, that gave me the path

/cards/ais/000/000/001/original/startransparentbrownsmall.jpg

My model looks like this:

  class Card < ActiveRecord::Base
  belongs_to :cardset
  ...    
  has_attached_file :ai, styles: {
    thumb: '50x50>',
    square: '100x100>',
    medium: '200x200>'
  }
end

Here's the code that worked:

        s3_file_path ="cards/ais/000/000/#{format("%03d", card.id)}/original/#{card.ai_file_name}"
        temp_dir_name = "#{Rails.root}/public/temp/pictures/cards/ais/000/000/#{format("%03d", card.id)}/original"

        temp_dir = File.dirname("#{temp_dir_name}")
        unless File.directory?("#{temp_dir_name}")
          FileUtils.mkdir_p("#{temp_dir_name}")
        end

        if File.exists?("#{temp_dir_name}/#{card.ai_file_name}")
          File.delete("#{temp_dir_name}/#{card.ai_file_name}")
        end

        s3 = AWS::S3.new(:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
                         :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'])
        bucket = s3.buckets[ENV['S3_BUCKET_NAME']]

        File.open("#{temp_dir_name}/#{card.ai_file_name}", "wb") do |f|
          f.write(bucket.objects["#{s3_file_path}"].read)
        end
        z.add_file("#{temp_dir_name}/#{card.ai_file_name}")

Here's the sites that helped me:

http://docs.aws.amazon.com/AWSImportExport/latest/DG/ManipulatingS3KeyNames.html

1: Is there a way to download a file from s3 using the ruby gem aws-s3? answer 2 by Nicolas Blanco

Community
  • 1
  • 1
flobacca
  • 936
  • 2
  • 17
  • 42
0

I think you want url not path

card.ai.path # => /bucket/model/id/file
card.ai.url  # => https://s3.amazonaws.com/bucket/model/id/file

you can go into rails console and check those values to be sure

z.add_file(card.ai.url)
# or maybe
z.add_file(open(card.ai.url))

also you can check your environment like so - instead of checking ENV directly

elsif Rails.env.production?
  # ...
house9
  • 20,359
  • 8
  • 55
  • 61
  • z.add_file(card.ai.url) didn't work and neither did open(card.ai.url). Did they work for you? I've been reading further and it seems that I have to ask aws S3 for the file with the proper S3::Bucket. – flobacca Jan 16 '14 at 19:38
  • see what `card.ai.url` returns and paste that into a browser – house9 Jan 16 '14 at 19:53
  • http://s3.amazonaws.com/bucketname/pathtofile. When I put it into the browser it says access denied. I have to have someway of telling the browser my public and private keys. I've already given my keys in my rails app, but I'm not sure of the ruby syntax to get the file out. – flobacca Jan 16 '14 at 20:34
  • `card.ai.expiring_url(600)` will generate a signed link that is valid for 5 minutes – house9 Jan 16 '14 at 20:48
  • I'm not looking for a link, I need to zip a file. I'm not really sure what your plan is. – flobacca Jan 16 '14 at 22:06
  • once you have a url that you can open in a browser, then you should be able to use that to add the files to your zip ? – house9 Jan 16 '14 at 22:26