Skip to main content

Join GoRails to continue learning

Subscribe to GoRails to get access to this episode and all other pro episodes, and new awesome content every month.

Subscribe Now
Only $19/month

Login to your account

24 Upload Progress with Refile Javascript

Episode 38 · January 3, 2015

Add background uploads and progress easily with Refile's JS library

Javascript Gems


Transcripts

Subscribe or login to view the transcript for this episode.

Discussion


Gravatar
Danny Wu (220 XP) on

Hello Chris, is there a good gem to build a progress bar? (for example, show % complete based on how many episodes you've watched)

Gravatar
Chris Oliver (167,500 XP) on

As long as you can calculate the percentage, all you need is some CSS. Bootstrap ships with a progress bar and all you need to do is set the width to the percentage complete. http://getbootstrap.com/com...

You can find many others if you're not using Bootstrap and you just google "css progress bar"


Gravatar
Anthony Candaele on

Hi Chris,

I tried to implement the immediate showing of the image from the cache, but it's not working. When I check the rendered code in my browser, I don't see the member_cache_id for the hidden field (in your example it's film_cache_id. The hidden field looks like this:

<input value="{}" type="hidden" name="member[image]">

I double checked the form field, it's exactly the same as the upload field in your example:

<%= f.attachment_field :image, direct: true %>

I also set the :image_cache_id in the allowed params of the member controller

So I'm not sure why the member_image_id is not set in the hidden field.

my code is at:

https://github.com/acandael...

greetings,

Anthony


Gravatar
Austin Story (10 XP) on

Hey Chris, do you know of a way to directly post to refile from a mobile app?

Gravatar
Chris Oliver (167,500 XP) on

If you pass the same parameters to the URL as the HTML form that gets generated it will work. Of course, you will need to make sure the mobile user has a way to authenticate as a user for that request by setting a cookie or using an API token. Mobile apps talking to a Rails app are basically the same as your browser, you just have to worry about things like cookies/API tokens.


Gravatar
Olivier on

For anyone using the latest version of refile (0.5.3), you will need to access cache_id differently because this is what gets returned.

<input value="{" id":"8c27104d22efe3de9b463bc8757e39ed2b632337e06628c2d8adf22c7b45","filename":"img_0741.jpg","content_type":"image="" jpeg","size":1064417}"="" type="hidden" name="user[image]">

image_info = $("input[name='user[image]']").val()
image_id = JSON.parse(image_info).id

Gravatar
Chris Oliver (167,500 XP) on

Looks like I'll need to amend this episode. Thanks for the heads up!

Gravatar
Anthony Candaele on

Hi Chris, yeah, I would be interesting to see a video on how to store uploads on Amazon S3, and other Refile configurations.

Gravatar
Guest on

I came up with the same code as above after I saw that the video doesn't match the current version of refile (0.5.3). However I found that it did't work, and the value of the hidden input was always null when I would try to get the id. It worked just fine in the console, but never from the page itself. So I wrapped the above code in:

setTimeout(function() { }, 0);

and it works fine.

Gravatar
Guest on

Never mind. I was binding to upload:complete instead of upload:success. I copied the code from the refile Github page, and it has the same code you have in the video, except it has upload:complete instead of upload:success like in your video. Makes sense why it wasn't working without the setTimeout now.


Gravatar
Anthony Candaele on

Hi Chris, is there a way to make the image_uploads.js.coffee script more generic, so that it's not only fetching film_image_id images but also for instance new_article_image_id images ?

greetings,

Anthony

Gravatar
Anthony Candaele on

found a solution with:

image_value = JSON.parse $("[id$=_image_cache_id]").val()


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
icsvortex666 on

Hi Chris :D, can you upload a tutorial on how to store the images on AWS using Refile (n00b here)
Thanks :)

Gravatar
Chris Oliver (167,500 XP) on

I can but it might take a while. In the meantime, you can check out their backend section. It pretty much walks you through it all. Just need to know your Key and bucket name from AWS. Just create your S3 bucket first and fill in the rest.

https://github.com/refile/r...


Gravatar
Marc Knapp on

Hello Chris,

I added your coffee script for displaying upload progess, but it returns an NaN error

$(document).on "upload:progress", "form", (e) ->
detail = e.originalEvent.detail
percentComplete = Math.round(detail.loaded / detail.total * 100)
$("#image").text("#{percentComplete}% uploaded")

Any ideas?

Thanks!

Gravatar
Todd Quillen on

Change the percent complete line to:

percentComplete = Math.round(detail.progress.loaded / detail.progress.total * 100)

Notice how "progress" was added after the detail in between the loaded and total.

Gravatar
Nikola Okonesh (210 XP) on

You have solved this problem?


Gravatar
Ariff Munshi (10,770 XP) on

Seems like the solution to show a preview image will not work any longer the latest version of refile. Even with Olivier 's suggestion to get the image id using the below code will not work as you will get a 403 (forbidden error).

image_info = $("input[name='user[image]']").val()
image_id = JSON.parse(image_info).id

Urls for version 0.6+ are signed with a token. Hence the new url will be:

imageUrl = '/attachments/' + token + '/cache/fill/360/360/' + imageId + '/image'

Will update this post if I find a way to do this. Or if anyone else has a solution, please do share.

Gravatar
Chris Oliver (167,500 XP) on

Yeah, with the new token system, this might be a piece of data you can get somewhere. I'd ask on the Refile Github issues and see what you find out. If you find a solution, let me know!

Gravatar
Ariff Munshi (10,770 XP) on

@excid3:disqus yea it seems that's it's not currently possible to do so.
https://github.com/refile/r...

Gravatar
Sz M (2,710 XP) on

@Ariff , I saw your issue posted on refile's github page where @jnicklas suggested to do a roundtrip to the server. Have you found a good solution for that?

Gravatar
Ariff Munshi (10,770 XP) on

Hey @szilardmagyar:disqus I did not implement a solution. For one of my apps I was still using the older version of refile and only admin are allowed to upload images. So there was no issue about the security bug.

As for my other app, I just did not implement the preview feature as I felt that it was not critical at this current moment. Will revisit the issue when I have the time. Nonetheless, I think a simple solution is to write your own javascript to show the image directly from your file system and not use Refile. So just add an image tag with the source as the file path of the image and load/show it using javascript. Doing a round trip to the servers will defeat the purpose as it will still only work after the image has been uploaded.

Hope this helps.

Gravatar
Sz M (2,710 XP) on

@Ariff, thanks for the quick answer! Do you have any code sample for that? I'm not that good at coding yet and not sure if I find the optimal solution. Thanks in advance!

Gravatar
Ariff Munshi (10,770 XP) on

Not my code but you can take a look at this:
http://jsbin.com/uboqu3/1/e...

Gravatar
Sz M (2,710 XP) on

Thanks Ariff!


Gravatar
Sz M (2,710 XP) on

Chris, if I upload a file with <%= form.attachment_field :message_attachment, direct: true, presigned: true, class: "choosefile" %> it gets uploaded to my s3 bucket (so everything seems to be working fine), yet when I display the filenames with url pathlike <%= link_to "#{message.message_attachment_filename}", attachment_url(message, :message_attachment),:target => "_blank" %>, it's served from my app (href=/attachments/....) instead of S3. Can you guess where things go wrong? Based on refile description files shouldn't hit my app at all with these settings.

Gravatar
Chris Oliver (167,500 XP) on

That's actually how it's supposed to work actually because it provides you the ability to generate different image sizes on the fly. The downside to this is it requires you to setup a CDN so that it doesn't have to generate the image every single request. You can check out the readme for some more information on that.

Gravatar
Sz M (2,710 XP) on

I will checkout with the CDN, but how can the files be served from myapp/attachments if the files never even touch the app (according to refile docs)?

Gravatar
Chris Oliver (167,500 XP) on

That's because the sinatra app (which Refile is referring to) gets mounted to your Rails app at /attachments. Rails basically routes the URL over to the Sinatra app, effectively so that the files never hit your Rails code. It just gets diverted before Rails would start processing it. And then files are served up from the same url because that's where the Sinatra app is.

Gravatar
Sz M (2,710 XP) on

So basically files are stored on S3, and when I try to use them in my app they will be fetched from S3 and get mounted by the sinatra app (to generate different size if pic), so an end user only will see the url as app/attachments? If so, is this the preferred way even if I don't want to display the picture? When I said display in my original question I meant displaying only the filename and the link to the url. My goal is to provide a way for users to send over each other jpeg/pdf/doc/etc. files. If they are interested in checking out a pic/doc/pdf then they can click on the file names which are listed in the app and the files get downloaded (doc/xls) or opened in a new tab with S3 (pdf/jpeg).

Gravatar
Chris Oliver (167,500 XP) on

You can setup Refile to cache some file metadata like the filename to your model. https://github.com/refile/r...

That should take care of showing the filename and then anytime the URL is clicked, then that's when Refile will download the file. Just displaying the link won't cause it to download the file just to render the filename in the link.

Gravatar
Sz M (2,710 XP) on

Thanks Chris!!


Login or create an account to join the conversation.