Skip to main content

34 File Uploads with Refile

Episode 37 · January 3, 2015

Learn how to upload files with the newest file upload library on the block: Refile

Gems File Uploading


Transcripts

This episode we're going to talk about the refile gem, and I'm really really excited about it. I'll post a link to this blog post in the show notes, but Jonas Nicklas, who has worked on carrierwave for a very long time has had a ton of experience supporting the rails community, and handling file uploads. That's not a trivial task. The file uploading stuff in rails is mediocre at best, I'll say. You've probably used paperclip, and paper clip you have to define all of the code in your models, we can pull up an example here. Thoughtbot did a great job on it, but the location of your code is a little bit confusing, and actually a lot of it is very confusing. In rails 4 you have an attached file, and you say: Let's have an avatar, and then let's crop it to medium and thumb, and here's the default url, and then let's validate the content type of it and so on, we have to create a migration, and we have to set multipart => true in our forms, and so on. It works, but you have to add like four columns to each of your models, you have to add validations, and then when it comes to doing things like Amazon S3, well you have to just keep putting more and more code in there in different places, so it ends up being a little bit messy. Now, carrierwave took a different approach, and carrierwave separated that code out into different classes. When you would say you wanted to add an avatar, they create the separate uploaders file, and that class inside of there is what defines like all of the things like the styles, like how to crop the images and so on. There's all these options and methods that you can define, like where to cache it, where to store it, what file types you want to allow and all of that. carrierwave was nice and it did many magic and stuff and you could process things, and it was not bad, but it still left a lot to be desired. Jonas Nicklas started this new gem called refile, and it's pretty awesome. I'm really really excited about it. Installation is really really short actually, you add these two gems, you add your attachment, and this user has a profile image, you add one string to your model, and then you have this attachment field, which is like file upload field, it's a helper for some other functionalities, you of course set up strong params for it, and then you have this magic attachment url that works quite a bit differently than what you might have seen. You notice here that we didn't define how to crop these images, well, that is defined in your views, so when you add in an attachment url, we say we want the profile image for the user, and let's crop it with the fill algorithm, and let's make it 300 by 300.

This happens on the fly with number three here, which is the magical rack application, so you have a rails app that's running, as well as a Sinatra app, and your rails app, when you upload a file, will send the image to the Sinatra app. It will do storage and everything, and then when you want to display an image with the image tag, it will actually stream the image back to you and resize it on the fly, so that's really nifty. One disadvantage of that is that you basically are required to have a CDN in production because all of this is happening on the fly, an that's a heavy tax for your servers, but pretty much every application should use a CDN in production anymore, and they're really cheap or free in some cases like CloudFlare. I'm really excited about this gem, one of the other things that I wanted to show you, and I welcome you to read through all of this, it's very well written and it explains a lot. For example, this shows the attachment field helper, how it automatically adds the encoding of multipart when you have the attachment field, and then it sets the hidden and type file in there so that it automatically handles all those exceptions when there's no file added and everything like that. The coolest part is that it comes with a JavaScript library that you can require with refile in your application.js, and then it adds this direct: true option. What that does, is it says right here, it immediately starts uploading the file as soon as the user selects it. They can fill out the rest of the form, but the JavaScripts will go back and upload it for you in the background. You've got these progress callbacks, and that's what people wanted. You upload files with paperclip or carrierwave in the background, and you had to use jQuery file upload, and it was a huge pain in the butt to do, and often was so unstable that it didn't work half the time. This JavaScript just comes with it, and you can just add these examples in, and for example this one disables the submit button until all the files are uploaded. That's really really nifty. What more could you want? It's only a few lines of code, really really simple. It also supports things like presigning uploads to go straight to Amazon S3, and you can say presigned: true, but you can also do background ones to Amazon S3 as well, so you can do the direct option there too. It's impressive.

Two last things before we dive into implementing this gem. So many people over the years wanted to figure out how they can remove the attached files, and this just comes with remove_profile_image attribute that you can set in your forms, so you can check that box, remove profile image, which is picked up by refile, and automatically gets rid of that attached file for you. That's nifty, and grabbing files by url, SO awesome, all you have to say is remote_profile_image_url and it will automatically fetch the image and then add it to the model. Plus, it follows any redirects too, so that's really cool, if you grab like an image from google or something, and the link redirected, then you'll still get the correct image as opposed to like just a 302 response. Refile, I'm really excited about, really happy with how it's designed, and the code that you implement with it, so we're going to take a look at our movie database that we did previously, and if you remember, I just took these images, and if we inspect this, you'll see that I just had a string column, and grabbed the image links from IMDB, we're going to replace this with refile, and we'll allow the image links like these, but we'll see how that changes, so we'll specify it using that remote_profile_image_url, and then we'll see what happens with the url when refile takes care of it.

Diving right in, we have this film model, and it has a url that is just saved as the image url attribute, and the same can be said about the actor model. We have an actor, we have the image url, and we're going to rename those and just basically change that to the image id that refile is going to use. First thing is first, let's paste in the mini_magick and the refile lines to our gemfile, you want to be careful here, because you need to specify these require options here:

gem 'refile', '~> 0.4.2', require: ["refile/rails", "refile/image_processing"]

If you don't do that, you're going to run into the missing attachment method inside your models, and so that is going to be requirement there. Make sure that you get that, save this file, you can run bundle to install it, and then let's just rails g migration RenameImageFields I'm going to name it that because we're actually going to take care of renaming both those image fields.

db/migrate/~timestamp~_rename_image_fields.rb

class RenameImageFields < ActiveRecord::Migration 
    def change 
        remove_column :actors, :image_url, :string
        remove_column :films, :image_url, :string 
        add_column :actors, :image_id, :string
        add_column :films, :image_id, :string
    end
end

rake db:migrate

Our columns got removed and added. You could rename this, it would keep the data that's currently in there, but that's kind of bad because the current string that are in there wouldn't actually match up to files that were uploaded to refile, so the existing data I wanted to blow away and that's how we're going to do that. Let's restart out rails server. Now, back in our models, we can add the attachment :image to each of these films and the actors, and then we can hop into the film form, and then we can change the text field that we had previously and reference the image now, instead of the image url, and we can remove this and change it to attachment_field. That should replace it with a file upload field now, and we'll check that out in a second in the browser, and then we'll also do this to the actor form here. Let's save that, and then refresh our edit page, and now we have an image upload field here, so we have the same form that we previously did, I just haven't styled it, but now we have a working file upload field. If we actually choose one of these images, and grab Keanu's face, and choose this, the JavaScript isn't added to the page, so this doesn't get uploaded in the background, this is going to happen when we click "Update Actor". Before we do this, we need to update the actors/show.html.erb page, and here we have the image tag for the actor image url, and that's not going to work anymore because we have this attachment url to use instead. We have

<%= image_tag attachment_url(@actor, :image, :fill, 300, 300) %>

We'll just use their example and see what this does. We can go to films/show.html.erb

<%= image_tag attachment_url(@film, :image, :fill, 300, 300) %>

Let's upload this actor, and we didn't get an image, so that's interesting. We have an image source of nothing, what happened was, we forgot to update the actor controller, and we need to change our strong params here to accept the image, and same with the films. We need to go to films_controller.rb, jump down to the bottom, and add in image. Now when we go do this, it removes the image actually, which is very cool. We can choose Keanu, and when we come back, when this page loads again, we get a 300 by 300 cropping of Keanu Reeves, that actually is really really neat. I ran into a bug here when I was trying to display this in rails 4.2.0 rc1. You may need to make sure that you're running a stable version of rails, not the pre release. I had to update rails to make sure that this worked but it did successfully, and we can go to our films now, and if we change this image tag here, and I was setting the style as a height of 150 pixels on the films index page, and we can go change this to the attachment URL, we can do an image tag for that. Now, we can say: instead of style as height that we can set

<%= link_to image_tag(attachment_url(film, :image, :fill, 150, 150)), film %>

These don't have images yet, we can edit them, we can add image for the Matrix, upload the film, the Matrix has it's image because it's square it didn't show up fully, so let's play around with these image tags, so you can actually go here and do anything you want. You can change these to 250 by 250, the image will be larger, you can change it to 50 by 150 and you will get a larger image, and all of that. You can do any of these of these options here, and they will change on the fly because of the way that this Sinatra application works. Here you can see that this file that gets requested in our logs is actually that image that we grabbed. When you run rake routes, you'll see this attachments url here that gets mounted to this refile app. This is your Sinatra application, and it's stored inside of the gem in the refile/app.rb It's the one that responds to these /attachments/store and here is the options that we give it, we told it fill, and we told it the width and the height, and this is the file name, so this is the id that is saved on our model. Let's just run rails console here and check that out. Let's grab the first film, and on the first film, "The Matrix" the image id is this big long string of text, so b873 is the first few characters of that, and you can see b873 is in the url, and then we are looking for the image attachment, so this is the url that the Sinatra app looks at, and then parses, and then returns that cropped image on the fly for you, so that's really nifty. The trouble with this of course is that every single request of this url, while it might be quick in development, you can see that it's very fast, this is going to be done thousands, or hundreds of thousands, or millions of times on your server if you have lots of users looking at images, and that's a lot of work. The CDN comes into play here, so that what happens is a user comes in, requests this page, and then hits the CDN first. The CDN looks at this image and then saves a copy of it, and then it's not loaded on the fly and cropped every single page view, it's loading the cached version of it. This is nifty, and that is a huge feature of this gem that you can just change any of this on the fly and see how it goes. It's very very useful. Now that we have that, let's try adding some other functionality in here. Let's go down to the Removing Attached Files, and we'll copy this checkbox for removing those, and then we'll also do the uploading images by url. I want to have a checkbox here that says the image here, we want to be able to remove it, so let's go into the film form, and then say:

app/views/_form.html.erb

<%= form.check_box :remove_image %> 
<%= form.label :remove_image %> 

films_controller.rb

def film_params 
    params.require(:film).permit(:title, :description, :image, :remove_image)
end 

Now, if we refresh this page, and we got an undefined local variable form because their example doesn't use f like I normally do, so now we have this "Remove Image" and we can display the image here so that we can see what it looks like. Let's just copy this from the films's show, and display the image. Let's do a small version, 100 by 100. You'll be able to see the preview of the image here, and if you check remove the image, you'll update the film, and the image is gone from here as well as the image has gone from here. That's pretty cool, I believe that we had a method to check to see if the film has an image. Let's test that out in our console, and let's say that Film.first, and now, the image id is nil, and we'll say image? It doesn't look like this image? method is provided by refile, but because this is simply a text string, then we can use image_id?, and it will tell us true or false if there's an image id saved to the database. Rather than talking to image?, they didn't create that method, which is fine. They might add it in the future, because I could see it being useful and very simple to add. Instead, now, if you want to check to see if an image exists, look at the image id column and check for it's presence there. Here, of course, we want to display the check box, remove image field if there is one. Let's say:

<% if @film.image_id? %> 
    <%= f.check_box :remove_image %> 
    <%= f.label :remove_image %> 
<% end %> 

Back in our browser, we can see that there is currently no image, and we can also wrap, if you see here, this field, we have the image with the empty source, and it's actually taking up some space here. If we delete it, it goes back to normal. We also want to encompass the image tag here inside that if statement. That way, we can display the image if there is one, as well as the "remove image" check box, and we can do the same thing here for the actor form, and we could paste that in, and we could replace film with actor, and that's that.

Now, our actors can have the same deal, but now, if we go to the actors page, we also are missing the actors index does not have the correct image tag, so we need to add the attachment url for the actor, the image, and we can set :fill, 150, 150 If we refresh that, we get back to 150 by 150 pixel image there.

That's all for this episode, I hope you enjoyed learning about refile and I definitely recommend checking it out, I don't know of any good examples of migrating you data from carrierwave of paperclip to refile, but if you find any links to that, definitely share them, I'd love to see that, and maybe we can do an episode on that in the future as well.

Discussion


Gravatar

Gravatar
Stan Carver (10 XP) on

Thank you for teaching the new Refile gem. The information shared in the Pro episode for upload progress is worth the subscription to Go Rails. In thirteen minutes, you communicated what has taken hours of work to implement with other file upload gems.

Question: With the refile gem, what is your recommendation for uploading multiple files in a single form, each with progress indicator? There is some discussion at https://github.com/elabs/re.... Perhaps another episode is in order?

Gravatar
Chris Oliver (170,390 XP) on

Thanks Stan! :)

I believe with multiple files (at least for separate things) you just say

class User
attachment :photo
attachment :resume
end

You may need to modify the Javascript somewhat so that it can tell the difference between the two. That likely is worth doing another episode on, some form of refactoring Javascript to handle this better.

The thing they don't handle right now is uploading multiple files (like User has_many :photos) but that should be coming soon. At least after reading that thread, it seems it should be easy for someone to implement it.


Gravatar
Jaroslav Horák (20,900 XP) on

It is Refile good for uploading video files? I need upload video files (not host them on youtube, vimeo, etc.) and maybe do some post production (format convert/generate, add watermark...).

Gravatar
Chris Oliver (170,390 XP) on

You can upload anything with it. You'll want to check out https://zencoder.com/en/ for transcoding. If you set Refile to upload to S3, zencoder can take it from there. https://github.com/zencoder...


Gravatar
Chris Kiklas (10 XP) on

If you are using the built in support for S3, it appears that you set that up in the initializer for refile:

# config/initializers/refile.rb

But what if you only want to use S3 in production, and the filesystem in dev and test? Is there a way to move this config to the environment level? For example, with Paperclip, the config to use AWS is here when you only want it in production:

# config/production.rb

Gravatar
Matt Vanderpol (10 XP) on

Chris, you can just setup an environment conditional in your initializer:


if Rails.env.production?
# Use S3 Backend
else
# Use FileSystem Backend
end
Gravatar
Nick Chernyshev on

Chris,
Rails 4.1 comes with pretty secrets feature so you can easily use it like this:


# config/initializers/refile.rb

aws = {
access_key_id: Rails.application.secrets.aws_api_key,
secret_access_key: Rails.application.secrets.aws_secret,
bucket: Rails.application.secrets.aws_bucket,
}

and then set different config options for different environments:


# config/secrets.yml
development:
aws_api_key: ...
aws_secret: ...
aws_bucket: ...

production:
aws_api_key: ...
aws_secret: ...
aws_bucket: ...

Gravatar
wbs on

Looking through the documentation it does not seem like there is any way to limit or throttle the reformatting/re-streaming of assets. I understand you say use CDN, but I do not see any method of stopping malicious users of hard spinning the asset urls with different pixel sizes for example to DoS the server... Any ideas or am I right in seeing this as a baseline flaw of this gem?

Gravatar
Chris Oliver (170,390 XP) on

Definitely a worthy discussion to be had with the author of the gem.


Gravatar
Anthony Candaele on

very cool gem indeed. Just implemented it to my new Rals app. Thanks for the very instructive video Chris!
I also need to implement document uploads (.pdf, .doc, .txt, etc ...) Can this also be done with Refile?

greetings,

Anthony

Gravatar
Chris Oliver (170,390 XP) on

Yep, shouldn't be a problem. You'll just skip the image processing parts.

Gravatar
Anthony Candaele on

ok, thanks!

Gravatar
Anthony Candaele on

just tried it out, and it works. I'm just wondering if there is a way to print the name of the document.

Gravatar
Anthony Candaele on

found a solution to print the filename of an uploaded file on this page:

https://github.com/elabs/re...

just generate a migration to add a filename field to the table, for example:

add_column :news_articles, :document_filename, :string

now you can read out filenames like this:

<%= link_to @news_article.document_filename, attachment_url(@news_article, :document) %>


Gravatar
alexander kehaya (900 XP) on

Can you use this to upload a CSV file and have each row render as a new object? What do you think is the best way to do this?

Gravatar
Chris Oliver (170,390 XP) on

CSV upload is definitely a topic I need to cover soon. I usually don't save the CSV files so I traditionally just use a file_field and let the file get deleted after the request is done in most cases.

Refile could work for storage of the CSVs though and then the model could access the file and parse it as necessary if you want to store the CSVs permanently.

Gravatar
alexander kehaya (900 XP) on

Thanks for the response. I'm going through this rails cast now http://railscasts.com/episo... to see if it works but I think I'm going to get a nokogiri error. I've had it before but going to see if I can debug. Would love to see this covered on GoRails though! Would be great to understand the parsing aspect.

I'll let you know how it goes for now.

Gravatar
Chris Oliver (170,390 XP) on

I will definitely record a screencast on this soon! Several people have been asking about it.

Also, check out this blog post that Patrick McKenzie just posted about his advanced CSV upload that he built: http://www.kalzumeus.com/20...

Gravatar
alexander kehaya (900 XP) on

I just read through the post. Seems pretty daunting.. Have been trouble shooting the rails cast. it appears he's able to upload csv files by about 3 min 12seconds in. I've got everything rendering correctly but am getting this error when I submit the file for upload. invalid byte sequence in UTF-8

I've been googling around but haven't found the right solution yet. Any ideas? I'm using ruby version 2.1.2
invalid byte sequence in UTF-8..

Gravatar
Chris Oliver (170,390 XP) on

Yeah it's very picky. You can google it and lots of people have similar problems. http://stackoverflow.com/qu...

Gravatar
alexander kehaya (900 XP) on

Ok yeah I found that one, went with the easy option of copy and pasting to google spreadsheets and then downloading it as a CSV and it worked. Now running into a pundit::NotDefinedError in SamplesController#import unable to find policy NilClassPolicy for. I'm a little confused because but I think I'll figure this one out.

Thanks again for the help.

Gravatar
Chris Oliver (170,390 XP) on

That'll work. :) I've just exported as a plain CSV similarly because it's hard to tell the encoding of the file sometimes.

As for the Pundit issue, sounds like the variable you're using Pundit against is nil (which is why it looked up NilClassPolicy). Double check that variable is getting set correctly and that should fix it.

Gravatar
alexander kehaya (900 XP) on

Thanks that pointed me in the right direction.. needed to define the variable @samples = Sample.all.. that got it working.

Gravatar
Nhat Tan Nguyen (130 XP) on

Maybe this gem can help you: https://github.com/singlebr...

Gravatar
alexander kehaya (900 XP) on

This worked great! Thanks!


Gravatar
Danny Wu (220 XP) on

Can you use this gem to upload multiple files at the same time?

Gravatar
Chris Oliver (170,390 XP) on

Not at the same exact time just yet, but that's on his todo list to add as a feature. https://github.com/elabs/re...

Gravatar
Danny Wu (220 XP) on

would be nice to have that feature. are there are currently available gems that support multiple file uploads (ones you would recommend)?

Gravatar
Chris Oliver (170,390 XP) on

I think Carrierwave does and I use it for almost everything right now.


Gravatar
lurker on

Has anyone made a rake task to populate the database with images? I went through the documentation and didn't see how this could be done. Thanks!


Gravatar
tujamaica on

I get this error when trying to use S3 backend:
/home/gabriel/.rvm/gems/ruby-2.1.5/gems/refile-0.5.3/lib/refile/backend/s3.rb:37:in `initialize': uninitialized constant Refile::Backend::S3::AWS (NameError)

Any ideas?

Gravatar
Comment_Again on

This is because Refile uses the 1.x version of the aws gem. You'll need to update your gemfile like this:

gem "aws-sdk", '< 2'

Now you'll be using the same version as Refile. The 2.x version of the aws-sdk gem uses Aws for name spacing instead of AWS so that you can use both versions of the gem in the same application.

Gravatar
Christopher Yeung (70 XP) on

is it still using aws-sdk < 2 now?
after 4 months.

Gravatar
Chris Oliver (170,390 XP) on

It's on aws-sdk 2 now. https://github.com/refile/r...


Gravatar
John on

I want to try and use Refile in my rails API app. Can I just attach a base64 encoded image in the post body?

Gravatar
andre bautista on

I'm curious about this as well, let me know if you find a solution!


Gravatar
Ariff Munshi (10,770 XP) on

Great video! Still deciding between carrierwave and refile tho since it's still new and carrierwave's wiki is filled with howtos. Btw, I think you missed out on the uploading via url part. :)

Gravatar
Chris Oliver (170,390 XP) on

I did forget to include that. It's an awesome little feature along with deleting uploads. It definitely still is pretty new and you can do everything with Carrierwave no problem.

Gravatar
Ariff Munshi (10,770 XP) on

Thanks Chris! Look forward to using it!


Gravatar
Daniel Borges Leal on

Can I check de md5, to prevent repeated uploads?

Gravatar
Chris Oliver (170,390 XP) on

That's a great question. You should ask in an Issue on the github repo for Refile.


Gravatar
claudiu claudiu (20 XP) on

guys, how to add more than one image?

Gravatar
Chris Oliver (170,390 XP) on

The best way to do it right now is to to upload each file to an associated has_many model.


Gravatar
Wilkerson Carlos (30 XP) on

Hi... Nice screencast! I'm getting a "no find image error" after deploy, using Capistrano... Seems like the app can't find the image after assets precompile... should i set up a directory for shared_children, or something like that? Thanks.


Gravatar
Jerome Doyle (20 XP) on

How would you do authorization on uploaded files with Pundit? I have uploaded files which should be restricted to the user that uploaded them, but anyone with the url that attachment_url generates can access the file. Since Refile uses the sinatra app, there's no controller for me to call Pundit's authorize method in.

Gravatar
Chris Oliver (170,390 XP) on

That's a great question and I don't particularly know the answer to that. I'm sure you can open an issue on Github and get a response.

Gravatar
Jerome Doyle (20 XP) on

Thanks for the reply. I've opened an issue on the repo. Direct link https://github.com/refile/r...


Gravatar
Juan Schwindt (10 XP) on

I've been using Dragonfly gem (https://github.com/markevan... for a long time and I find it very similar to Refile. Has somebody compare them to have a better idea if it is worth adopting Refile?

Gravatar
Chris Oliver (170,390 XP) on

Looks similar but I've never used Dragonfly. Unless you need some other feature, it probably isn't worth switching yet.


Gravatar
Joseph Jang (10 XP) on

The problem I had with Carrierwave was that when I used my phone to upload an image, I couldn't use my Gallery to upload an image (the gallery did not pop up as one of the ways to upload the image). Instead, I had to find my images in different folders, so I had to go to My files folder-> DCIM -> select the image, which is not a very good user experience (I was using an Android by the way).

I was wondering if I use Refile on my phone, will I be able to select images from my gallery directly? Or, would it be the same UX as Carrierwave where I have to navigate into my folder (i.e. DCIM).

Gravatar
Chris Oliver (170,390 XP) on

Unfortunately that wouldn't make a difference. That feature is controlled entirely by the browser on the device. It will work differently depending on the OS version and browser.

One thing you can try is to play with the accept and capture attributes on the file field itself and see if it will trigger different things on your Android browser. I can't find great documentation on it though, but check this out to get started. http://stackoverflow.com/qu...


Gravatar
Joseph on

Would you recommend Refile for users - posting videos? Or, would Zencoder work well with Refile??

Gravatar
Chris Oliver (170,390 XP) on

Any uploader that submits the file to S3 will work with Zencoder. They expect that your original video file is already available on S3 so they don't have to worry about which uploader you use. You're free to go with Refile, Carrierwave, Paperclip, etc.

Gravatar
Joseph on

Thank you for the explanation. If you want to create a site like Udemy, where you allow users(lecturers) to upload multiple number of videos to sell, do you know any tutorial or resources that you recommend? Thank you in advance!

Gravatar
Chris Oliver (170,390 XP) on

You would create a new "Lesson" record for each each video and have one video upload per Lesson. Do the same as this basically and you're all set. It would be just like creating multiple Film records for the same Actor.


Gravatar
Guest on

hi there! love these tutorials! I would love to get your opinion about Transloadit !!! ???? It seems super awesome but I was unable to populate mysql with URLs after the robots did their jobs and packaged up JSON Assemblies on the Transloadit API.....just wondering if you think this service is worth using, etc. THANKS!

Gravatar
Chris Oliver (170,390 XP) on

This looks super cool. I haven't used it before, so I'm not quite sure how they return the urls afterwards. I have previously seen a lot of people using https://www.filepicker.com/ in the past.

I think they're definitely great and give your users a lot of flexibility as well saving you from a lot of time managing the files and processing them. Would definitely recommend it if file uploading is something you don't really need to manage or customize too deeply.

Gravatar
2gingersnaps on

- thanks again for the great tutorials! much needed! I will let my fellow rails friends know about this when I attend an upcoming Rails meetup!

Gravatar
Chris Oliver (170,390 XP) on

Ah it looks like it's sending webhooks back. Those are always a bit tough to test in development because your dev server isn't publicly accessible on the internet.

Thanks for sharing GoRails! :)

Gravatar
2gingersnaps on

gotcha! thanks!! go GoRails!


Gravatar
Marco Brinkmeier (140 XP) on

Thank you for your videos!! I want to upload a image from a external application. How I can do that? I didn't find documentation about that.

Gravatar
Chris Oliver (170,390 XP) on

Lots of different options here. Are you talking about importing files from somewhere else like through a Ruby script or something? Where are the images in the external application? Does it have an API?

Gravatar
Marco Brinkmeier (140 XP) on

The image files (e.g. jpg) will send by android. The idea is that the rails app receive the base64 encoded image file as a HTTP POST request and save it with Refile.

Gravatar
Chris Oliver (170,390 XP) on

Sending files via a POST won't be any different than a normal upload form on the webpage. The browser submits forms with a POST so if your Android app or mobile browser does the same thing, nothing would change. You just need to make sure the file is sent over with the same field name as it has in the browser so it can attach to the right model and attribute.

Gravatar
Foliwe Fossung (70 XP) on

please can you make a deployment to heroku with aws video with refile gem

Gravatar
Chris Oliver (170,390 XP) on

I don't use this anymore, but I would recommend just following the readme for the S3 example they have: https://github.com/refile/r...

Their Github would also be the best place to ask for questions on S3 as well.


Gravatar
Johnny Mnemonic on

Hi, thanks for this solution.
I new in Rails world.

Can i use this gem for upload large file (4gb+) on my locale-storage, without S3?
And in upload process "uploading file" writing in RAM memory or on hdd in temp?
(Because i have problem with simple upload form, first file write in RAM mem, and after in tmp file.)

Thanks.

Gravatar
Chris Oliver (170,390 XP) on

That's a great question. I think Refile might not be ideal, but you can always ask the author on the Github issue tracker.

Another useful resource is: http://bclennox.com/extreme...

Gravatar
Johnny Mnemonic on

Thanks, Chris.


Gravatar
Christopher Yeung (70 XP) on

Wondering if refile supports renaming files, when directly uploading to S3


Gravatar
Christopher Yeung (70 XP) on

Everything seems to work except after i follow the S3 steps, it still uploads to localhost.. any thoughts?

Gravatar
Gravatar
RJ McCollam (1,720 XP) on

I am having the same problem as your initial one. Did you figure it out and is that why you posted a link to your repo? Could you elaborate on what you did to correct it?

Gravatar
Chris Oliver (170,390 XP) on

Check out this section in the Readme which should get you sorted out. https://github.com/refile/r...

Gravatar
Christopher Yeung (70 XP) on

I moved back to paperclip..

Gravatar
RJ McCollam (1,720 XP) on

I thought that this was happening to me too, but when I actually thought about it I saw it was working. Even if you upload to a 3rd party host the rack app for refile will download that image, process it, and still give it a local URL. The true test to see if it is uploading to S3 is to look in your bucket to see if the images are being stored there. Turns out mine was working all along.


Gravatar
Muhammad Hafiz (10 XP) on

Is it possible to do image preview before we actually save the image?

Gravatar
Chris Oliver (170,390 XP) on

Yes you can. This isn't specific to Refile, but just some regular Javascript hitting the browser File api. http://jsfiddle.net/LvsYc/


Gravatar
Jamces on

Looking for a way users can upload videos - there isnt much out there that clearly explains


Gravatar
Sz M (2,710 XP) on

Chris, I started using refile with more models (product model for avatars and message model for file sending) and realized all the things go to the same folder on S3. I also wanna upload files for the product model but it would be messy if everything was in the same folder (product avatar, product files and message files). I guess I will change the product avatar uploader to use carrierwave, but still the product files and message files will go to the same S3 folder which is not the best I guess. As I see in the docs/issues on github there is no way to put them into different folders. Did I miss something and I can put them into different buckets somehow? If I can't how I can make sure everything will be fine down the road?

Gravatar
Chris Oliver (170,390 XP) on

I'm not sure why this isn't the default. It's a really important thing for managing a large set of files, so you'd think this was already in there.

I see a prefix option for the library that allows you to do this, but I don't see much information on how you'd set that dynamically.

This is the prefix option I'm talking about. You would need this to be set dynamically each time a different file type was uploaded which I don't know is very easy to customize.

Refile.store = Refile::S3.new(prefix: "store", **aws)

It's probably worth opening a Github Issue on the Refile to ask about this and see if there's currently a way to do that or if a patch needs to be made to support it.

Gravatar
Sz M (2,710 XP) on

I've checked it out already, but it's a bit high level, so I don't understand it. https://github.com/refile/r..., https://github.com/refile/r... I just thought you have also run into this problem since as far as I know you are using refile gem. Chris after writing this comment I found an answer on stackoverflow which might be useful. If so I will circle back with the solution. I guess it's important for everybody here.


Gravatar
Ayman Jaa on

What about paperclip ?


Gravatar
Neba Funwi-gabga (90 XP) on

There appears to be a problem with refile gem when using nested forms? I have a profiles form nested inside a users form, but when I upload the image, nothing happens. No errors are given, but profile images are not uploaded either. Anyone noticed this?


Gravatar
Neba Funwi-gabga (90 XP) on

Thanks for this episode Chris. I implemented this and it works on my development server just fine. But when I deploy to production (Digital Ocean Ubuntu 16 with Capistrano and Nginx), i see the images upload just fine to s3 bucket, but unable to retrieve them. My nginx error log says:
"App 494 stdout: Refile::App: Error -> ImageMagick/GraphicsMagick is not installed"

but I have both imagemagick and graphicmagick installed on my server. What could be the problem here?

Gravatar
Chris Oliver (170,390 XP) on

It's possible that Refile just isn't able to find the executable for imagemagick. It's looking for the "identify" command so you'll want to make sure that's in one of the folders in the PATH for the same user that Nginx is running as. I'd poke around at that and see if you can figure out why it might not be able to find the identify executable. If you installed imagemagick with apt-get then it should be available, but if you compiled it or something else, then it's probably just not in the PATH.

Gravatar
Neba Funwi-gabga (90 XP) on

Thanks Chris, but Yes I installed with apt-get and when I do "which identify" it shows /usr/bin/identify. I also have the /usr/bin in my PATH, but still getting the same error. I used your other tutorial on "Deploying to Digital Ocean" to do the deployment...think there's anything in there that could cause this?

Gravatar
Chris Oliver (170,390 XP) on

Hmm, sounds like you've got everything correct! I have used the exact same setup before and it works fine. I'll have to think on it and see what comes to mind.

Gravatar
Neba Funwi-gabga (90 XP) on

OK Chris I got this working...maybe someone else is facing the issue but this is what I realized...RoR was not picking up environment variables, so the PATH which indicates the location of Identify executable was not being read. What I did:

1- In my ~/.profile I made sure it was loading both .bashrc and .bash_profile (initially it was only loading .bashrc)

2- I then created a ~/.bash_profile, where I put in my environment variables:
eg
export PATH=$PATH
3- Restarted the server: sudo service nginx restart

Bammm...with this my images showed up and even my SMTP settings which were also not working are being picked up now. Thanks for your suggestions.

Gravatar
Chris Oliver (170,390 XP) on

Glad you got that working! Certainly seems weird that it wasn't picking up any environment variables! I don't think I've ever run into that, but it makes sense why you were having that problem then.


Gravatar
blazetango (30 XP) on

Can any one please help. i need to crop the image before uploading the image file to refile
couldnt find any solution with refile to crop the image.
Thanks


Gravatar
Foliwe Fossung (70 XP) on

please can you make a deployment to heroku with aws video with refile gem


Gravatar
alexander kehaya (900 XP) on

If anyone runs into dependency issues with Rails 5 I found a good solution here: https://github.com/refile/r...

Gravatar
Jake Yeaton on

Thank you so many times over. This was a life saver!


Login or create an account to join the conversation.