I have a Rails 4 application running on MongoDB and I use Paperclip (4.3) for the uploads. Everything works fine.
Now I'm building a REST API with Node.js and Mongoose to serve some of the data and I'm having trouble understanding how I can generate the URL for the paperclip attachments with Node.js.
Here's the relevant part of one of the Rails models:
has_mongoid_attached_file :thumb,
:url => "/assets/images/templates/:hash.:extension",
:path => ":rails_root/public/assets/images/templates/:hash.:extension",
:hash_secret => "somesecret"
The fields generated in the MongoDB document end up looking something like this:
"thumb_file_name" : "test-19103515.jpg",
"thumb_content_type" : "image/jpeg",
"thumb_file_size" : 76864,
"thumb_fingerprint" : "00dab4127977a69ab264d79202f5f799",
"thumb_updated_at" : ISODate("2018-03-28T03:32:36.454Z"),
and the URL of the file looks like this:
/assets/images/templates/3666b3ef97b492b27b108fd215c397d2435d5fcb.jpg?1522207956
Basically what I am asking is if anyone know how to generate the hash that paperclip generates so that given the hash_secret i can get in this case the resulting 3666b3ef97b492b27b108fd215c397d2435d5fcb hash.
Note that I am aware that there is a node-paperclip npm package but I only see there upload examples while what i need is to be able to generate the full URL of an attachment already uploaded by the Rails app. If by any chance one of you knows how to do that with that package I'll be happy to use it.
Related
I would like to migrate from Paperclip to Carrier Wave or Refile because of this. The solution written here is impressive, but strikes me as complex and perhaps brittle.
My Rails4 app has 100's of images in production that were uploaded with Paperclip. Files are stored on production server. I have looked for a complete set of steps to follow to migrate, but keep coming up empty.
Is there a set of steps one can follow that allows for migration without necessitating application code re-write?
Alternatively, is there another way to persist uploaded files in Paperclip when form validation fails?
What am I missing here?
UPDATE:
Tried the solution detailed here by https://stackoverflow.com/users/646389/galatians . My paperclip :path and :url interpolations make use of :id_partition. I don't see a way this can be reconciled with an uploaded Image that is staged, but not yet saved.
I migrated to Carrierwave. Here are the relevant stats:
Time to work on and fail at coding a solution for persistent files
across form reloading with Paperclip - 4 hours. See OP update for the issue I could not overcome.
Time to Migrate to carrierwave, adjust the relevant models, controllers, and forms, and test. - 2 hours. Not so bad.
This key info helped me adjust the paths correctly. Keeping the path identical was important to me for avoiding having to move images to a new location in production:
Carrierwave code for generating paperclip-like :path and :url info here.
Paperclip interpolation info here.
This link got me on the right track, although my default :path made use of :id_partition not :id.
UPDATE:
Migration breaks this paradigm:
#protocol.images.each do |i|
tmp=i.dup
tmp.avatar = File.open(i.avatar.current_path)
tmp.save!
#dest.images << tmp
end
See: Duplicating a record that contains a carrierwave avatar : Getting "can't convert nil into Integer" error
You don't need to do anything because the only data needed to get images is already stored in DB.
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
For Ruby on Rails I want to use
<img src =../../../photo/1.PNG >
to show some images stored outside my app folder. I use this and use .. to point out where image it it , But it does not work。 I use Win7, Is there anyone could help me ?
I have a MVC named "showcase" generated by scaffold, and I wanna to have the same showcase in two apps.
In app1: showcase (where I wanna to share the images)model: house is the image name.
class Showcase < ActiveRecord::Base
attr_accessible :house,:sequence
has_attached_file :house, :whiny => false,
:styles => { :large => "350x300>",
:medium => "120x100>",
:thumb => "50x50>"}
end
then the images will be uploaded in the folder: public/systems/showcases/houses/000/000/0001/1.PNG
in app2. I create a showcase model with migration. and use ActiveResources share the database between app1 and app2. but app2 can not configure paperclip type.
class Showcase < ActiveResource::Base
self.site = "http://localhost:3000"
end
how can I in app2, call images uploaded from app1.
If your trying to really share images between applications, and they are uploads and not static assets then create a systems folder somewhere else, then make the system folders in each app a symlink to the share folder. That way your not having crazy url paths, and they both can asses it, and you wont end up with dupes or mismatches.
You should really use the rails assets pipeline if you are using rails 3 or above. Put your images in app/assets/images and call the rails functions that gives you url to the assets e.g. <%= image_tag "rails.png" %>.
For more detail read the following guideline:
http://guides.rubyonrails.org/asset_pipeline.html
I am in the process of upgrading my rails app from 2.3 to 3.2, and I am having a problem with paperclip. My app was previously using paperclip v2.3.5 and now I am using rails 3.0.20 with paperclip v3.3.1
The problem happens when I try to upload an avatar to S3. It looks like paperclip is escaping the path before sending it to S3, but when I ask for the url of a specific style, the url uses an unescaped version of the path, and this leads to a "NoSuchKey" error from S3 (more like a 404 not found)
In my model I have
Paperclip.interpolates :last_modified do |attachment, style|
attachment.instance.updated_at.to_i
end
:path => "folder/:id/:style.:extension?:last_modified",
:url => ":s3_domain_url",
So the old version of my app was using urls from S3 like:
http://my-bucket.s3.amazonaws.com/folder/123/thumbnail.png?123456789
But now, everytime I upload an avatar, S3 will store the url like this:
http://my-bucket.s3.amazonaws.com/folder/123/thumbnail.png%3F123456789
and asking my model for the url of thumbnail style, will return:
http://my-bucket.s3.amazonaws.com/folder/123/thumbnail.png?123456789
which S3 can't find.
I know it seems to be an easy to fix issue, but my main concern is that the production app has a lot of users with many pictures and updating all of their images is a delicate task, and manually escaping the question mark is not a solution.
I just figured out how to fix a problem that was similar to this. There is a new escape_url option. Maybe try turning that to false?
:path => "folder/:id/:style.:extension?:last_modified",
:url => ":s3_domain_url",
:escape_url => false
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