I am uploading an image to a ruby on rails server using a gem called paperclip. The image is uploaded correctly and is working. I am working on using md5 hashes so that a single request to the rails server can be made, returning to my script exactly what images need to be uploaded (I do not want duplicates).
In the script I am calculating the md5 successfully with
require 'digest/md5' and md5 = Digest::MD5.file(filename).hexdigest
On the server in order to check if the md5s are the same (image to be uploaded vs image on the server) I need to calculate the md5 of each paperclip image on the server.
Images are called TestImages and the model looks like this
class TestImage < ActiveRecord::Base
has_attached_file :image, styles: {thumbnail: '100x100', small: '350x350'}
validates_attachment :image, content_type: {content_type: ["application/octet-stream", "multipart/form-data", "image/jpg", "image/jpeg", "image/png", "image/gif"]}
belongs_to :build
belongs_to :test
end
People have said that paperclip has added the functionality of a fingerprint (md5 representation) but I am unsure as to how to set that up. It seems it is done automatically but needs to be stored as a column in the database? Here is one other post I was looking at Rails: How does MD5 checksum work in paperclip?
If it doesn't work with using paperclip (paperclip fingerprint) I could do the same digest/md5 method as in the script but I can't seem to find the full image path of the paperclip image.
Using this did not work
image.md5 = Digest::MD5.file(test_image.image.path).hexdigest
This gave the following error:
Errno::ENOENT (No such file or directory # rb_sysopen - /Users/scott.bishop/Code/visual-automation/public/system/test_images/images//original/testBasic_2x.png):
app/controllers/test_images_controller.rb:37:in `create'
I'm not sure what path it wants. Any help would be much appreciated.
It turns out that the paperclip image path works.
require 'digest/md5'
image.md5 = Digest::MD5.file(PAPER_CLIP_IMAGE.path).hexdigest
Related
I am trying to seed multiple image attachments to a model. I have been using this link but I am still sort of stuck since what I aim to do differs a little since:
I am trying to attach multiple images to each object (which I seed) in the model
I want to retrieve these images from my S3 bucket and attach them to the objects (is this possible?)
Here's my seed.rb:
shirt = Item.create(name:"Basic Shirt",price:19.99)
skirt = Item.create(name:"Basic Skirt",price:29.99)
sweater = Item.create(name:"Basic Sweater",price:39.99)
kid_hood = Item.create(name:"Basic Kid Hoodie",price:19.99)
# somehow attach images here?
I am using the aws-sdk-s3 gem in order to connect Active Storage to my S3 bucket. Please tell me if any additional files are needed for viewing. I will happily edit this post to include it.
ActiveStorage work on plain byte streams, so you can download the file (using open-uri for instance) and assign the stream as the content of the attachment.
Assuming you have the following (adapt if different)
class Item < ApplicationRecord
has_one_attached :photo
end
you can have your seeds as:
require 'open-uri'
shirt = Item.create(name:"Basic Shirt",price:19.99)
shirt.photo.attach(io: open('your-s3-nonexpiring-url'), filename: 'foo.bar')
# ...
Just a note: as of Ruby 3.0, you will need to call URI.open instead of open. See the reference to open-uri here.
I am trying to get images to upload as flyers for events. I do have the parameters configured in the controller. No error is being shown, but the actual image is not rendering in the view (all you see is the filename).
When I upload an image file in production (hosting with Heroku) it saves properly and I can see the file name and size in the console. I can even go to my Amazon S3 console and look at the actual image from there.
This makes it hard for me to tell what's wrong.
I have a hunch that I'm about to try out (among many other things). The only thing I think it could be is that I haven't configured the url to the location of the file in my S3 bucket, but so far I haven't found out exactly how to do that...
In case you're wondering, I do believe I have the code for the view, controller, and model written properly. But the model does make me curious. Here it is just in case:
event.rb
has_attached_file :flyer,
styles: { medium: '300x430#', thumb: '123x170#' }
validates_attachment_content_type :flyer, :content_type => /\Aimage\/.*\Z/
private
def flyer_size
if flyer.size > 5.megabytes
errors.add(:flyer, 'must be less than 5MB')
end
end
Any ideas on what's going on?
EDIT:
When I inspect element this is what it shows.
<img src= "https://s3.amazonaws.com/[bucketname]/events/flyers/000/000/008/medium/JAM.jpg?1436400492" alt="Jam" >
::before
</img>
I was using the Paperclip gem: https://github.com/thoughtbot/paperclip
I'm now using Carrierwave: https://github.com/carrierwaveuploader/carrierwave
My production website is currently using Paperclip. I'm going to be updating the production website to use Carrierwave.
The folder structure for uploads in Paperclip differs from Carrierwave.
I'm also using Amazon S3 to store uploads.
I'm wondering if there's a way to convert my production files uploaded with Paperclip to Carrierwave.
For example, with Paperclip in production I currently have something like the following for resumes:
bucket_name/model_name/resume/000/000/model_id/original/test.pdf
With Carrierwave it should be:
bucket_name/uploads/model_name/resume/model_id/original/test.pdf
Right now it seems I have to make this conversion manually. I was wondering if there's a better approach.
Please advise.
The CarrierWave::Compatibility::Paperclip module already provides this functionality. Just do the following in your uploader:
class MyUploader < CarrierWave::Uploader::Base
include CarrierWave::Compatibility::Paperclip
# The :id_partition symbol will trigger a proc in the Paperclip compatibility module that will build out the properly partition directory structure
def store_dir
"#{model.class.to_s.underscore}/#{mounted_as.to_s}/:id_partition"
end
end
Have you tried changing the store_dir options define in carrierwave uploader to look exactly like that of paperclip
def store_dir
"#{model.class.to_s.underscore}/resume/#{id_partitioning}/original/"
end
def id_partitioning
("%09d" % model.id).scan(/.{3}/).join("/")
end
Note : I just done remember how the paperclip does the id_partitioning (how much '0' it pad to the left based on object id )
but based upon your format 000/000/model_id look to me like 9 character Please confirm
Hope this help
Sorry for maybe dumb question, but I have some misunderstanding about how Paperclip works. If I use it with aws-sdk gem, where image urls are stored?
My model has only fields like image_name, image_size, but not something like image_url. I also tried to list all tables from my db in sql console, but there wasn't any special image-related tables. I know what I can access url by calling my_model.image.url, but I need understanding, where this url is located.
Thanks.
The urls are auto generated based on the ruleset you have in your paperclip config file. They usually include the name and id of your model unless you have changed the defaults. Set the :default_url option when you call has_attached_file if you want to change it:
:default_url => '/images/:attachment/missing_:style.png',
:path => "avatars/:id/:style/:filename"
More background: rails paperclip default image with S3
I'm using Paperclip / S3 for file uploading. I upload text-like files (not .txt, but they are essentially a .txt). In a show controller, I want to be able to get the contents of the uploaded file, but don't see contents as one of its attributes. What can I do here?
attachment_file_name: "test.md", attachment_content_type: "application/octet-stream", attachment_file_size: 58, attachment_updated_at: "2011-06-22 01:01:40"
PS - Seems like all the Paperclip tutorials are about images, not text files.
In Paperclip 3.0.1 you could just use the io_adapter which doesn't require writing an extra file to (and removing from) the local file system.
Paperclip.io_adapters.for(attachment.file).read
#jon-m answer needs to be updated to reflect the latest changes to paperclip, in order for this to work needs to change to something like:
class Document
has_attached_file :revision
def revision_contents(path = 'tmp/tmp.any')
revision.copy_to_local_file :original, path
File.open(path).read
end
end
A bit convoluted as #jwadsack mentioned using Paperclip.io_adapters.for method accomplishes the same and seems like a better, cleaner way to do this IMHO.
To access the file you can use the path method:
csv_file.path
http://rdoc.info/gems/paperclip/Paperclip/Attachment#path-instance_method
This can be used along with for example the CSV reader.
Here's how I access the raw contents of my attachment:
class Document
has_attached_file :revision
def revision_contents
revision.copy_to_local_file.read
end
end
Please note, I've omitted my paperclip configuration options and any sort of error handling.
You would need to load the contents of the file (using Rubys File.open) into a variable before you show it. This may be an expensive operation if your app gets lots of use, so it may be worthwhile reading the contents of the file and putting it into a text column in your database after uploading it.
Attachment already inherits from IOStream. http://rdoc.info/github/thoughtbot/paperclip/master/Paperclip/Attachment
So it should just be "#{attachment}" or <% RDiscount.new(attachment).to_html %> or send_data(attachment). However you wanted to display the data.
This is a method I used for upload from paperclip to active storage and should provide some guidance on temporarily working with a file in memory. Note: This should only be used for relatively small files.
Written for gem paperclip 6.1.0
Where I have a simple model
class Post
has_attached_file :image
end
Working with a temp file in ruby so we do not have to worry about closing the file
Tempfile.create do |tmp_file|
post.image.copy_to_local_file(nil, tmp_file.path)
post.image_temp.attach(
io: tmp_file,
filename: post.image_file_name,
content_type: post.image_content_type
)
end