4

I've recently installed Fine Uploader to our Rails app. I've read documentation and experimented a little with it, but I don't seem to understand how this thing actually works, and because of that, I'm having a lot of problems implementing it.

What I did: Installed it (two ways, one "classical" and the second using the fineuploader gem, which seems to do the same).

Created a coffee file containing this.

$ ->
  uploader = new (qq.FineUploader)(
    debug: true
    element: document.getElementById('fine-uploader')
    request: endpoint: '/uploads')
    template: 'test-template'

And that creates an "upload a file" button (which of course does not work, cause there is no configuration to handle this on the server site), but I would like to have this button in the simple-form input field.

Also, templating does not work, I don't really understands why.

Unlucky, documentation lack help for Rails.

I'm open for changing this library to something else, as long as it contains the features that I need which are:

  • pausing and resuming download
  • file chunking (in case of failure, user won't be forced to start over)
  • progress bar (not vital)
ZebThan
  • 255
  • 2
  • 17
  • There is an [entire documentation site](http://docs.fineuploader.com) and guides that walk you through setting up fine Uploader for various workflows. If you need specific help, you will need to provide more information than "it doesn't work". What specifically is happening or not happening? – Ray Nicholus May 25 '16 at 12:19
  • @RayNicholus What does not work, is the uploading process, but it is not meant to work at the moment. I mean, I've never configured this, and I'm not going to, because I want to use functionality that is already in Rails, so everything is nice and clean. Templates are not really important at the moment, but truth is, I don't know what this part does: Putting something inside doesn't really seem to change anything or I fail to notice the change. The rest work like a charm. – ZebThan May 25 '16 at 12:42
  • What log messages are you seeing in the browser console? – Ray Nicholus May 25 '16 at 12:53
  • Only when there is "template: 'test-template'. Error: element not found list Additionally, there is almost nothing in the #test-template. Just some random text to see what it is doing. – ZebThan May 25 '16 at 13:03
  • Why is there "almost nothing" in your template? You must have valid elements in your template, as described in the library docs – Ray Nicholus May 25 '16 at 13:46
  • First I've copied the one from the example, but nothing was happening. So I've been striping it, bit by bit (to find what is causing a problem), until nothing is left. It seems, that this script is being totally ignored. – ZebThan May 25 '16 at 14:47
  • 1
    What _specific_ messages do you get in the browser _console_ when you have a _valid_ template? – Ray Nicholus May 25 '16 at 15:00
  • Ok, I found the problem. Actually the rails gem is not very reliable (not at all, as it seems). I've deleted everything, and installed it manually, and now it works. Still remains the question about what is the best way to do this in Rails. If there will be no answers, when I'm done with it, I will post an answer with my solution. – ZebThan May 25 '16 at 15:52
  • Yes, please do post an answer. Whatever rails gem you are using is not something I've maintained or seen. Can you point me at the GitHub repo for this gem? Perhaps I can start a discussion with the associated dev(s) that will align it a bit more closely with the Fine Uploader library. – Ray Nicholus May 25 '16 at 16:49
  • @RayNicholus Here's the gem I've been using: https://github.com/mezis/fineuploader-rails And here's another gem, but I think it's the same idea, and both won't work. https://github.com/zakgrant/fine-uploader-rails But it just seems that their both are old. My guess is, that you've developed fine uploader a lot since gem got it's last update, and is simply outdated at the moment (version 3.x so yeah, outdated). – ZebThan May 27 '16 at 08:24
  • Both of those repos are dead - last commit in mid-2013. It's pretty likely that they simply won't work anymore, since the current version of Fine Uploader is 5.9.0, and those target 3.x. Have you figured out your original issue yet? I'm not versed in Ruby or Rails myself. If you have come up with a solution, I'd love to talk about getting an updated Rails or Ruby example into the Fine Uploader GitHub organization. – Ray Nicholus Jun 01 '16 at 14:27
  • @RayNicholus - Thought so. At the moment I'm finishing it, but it is mostly a prototype. After it will go live, I will write a solution here. About this example on git hub, it will be my pleasure to contribute. – ZebThan Jun 01 '16 at 14:42
  • 1
    After you have something working here and are able to post an answer, I'll follow-up with a plan for getting something into the GitHub org. – Ray Nicholus Jun 01 '16 at 14:53

1 Answers1

9

I've managed to make it work, and I have some knowledge about how it works, so I'm going to share this knowledge. But I want to strongly point out, that I have figured this on my own, so there might be flaws in what I'm providing. Use your knowledge and experience, and if you think something can be done better, you may be right.

First of all, download the library using npm. I have found two gems for it, but don't use them. At the time I'm writing this, those gems are outdated, and won't be working. Github links:

github.com/mezis/fineuploader-rails
github.com/zakgrant/fine-uploader-rails

If you happened to download those, you will have to reinstall library.

After that, you will be creating the javascript. I've created a file called "fine-uploader.coffee", and put there something like this:

$ ->
  uploader = new (qq.FineUploader)(
    element: document.getElementById('fine-uploader')
    request:
      endpoint: '/upload'
      params:
        authenticity_token: $('#fine-uploader').data('authenticity-token')
    template: 'template-name'
    chunking:
      enabled: true
      mandatory: true
      success:
        endpoint: "/upload/finish"
)

I'm not going to describe what is what, because all of this can be found in the docs, instead I'll focus on what is important for us. In the "request" you have an endpoint, for this case, we will need to add it to our routes, like this.

post 'upload', to: 'uploads#create'

Then, we will need to create our controller. As you can see, I've created dedicated controller for handling uploads, and I recommend you doing so.

In the uploads controller we have this action:

def create
    file = params[:qqfile]

    #code that does whatever you need

    respond_to do |format|
       format.json {
          render json: { success: true }
       }
    end
end

In your controller, you will have some params (you can check all of them in the docs), but the one that is important to you is qqfile. This will be the file, that was posted. You can do whatever you want with it. I was using carrierwave to save and process it, and I guess this does not require further description (as you can find it in the carrierwave dosc, also, you maybe using something else, like refile).

You will also have to add a parameter with token, you can see it in the 7th line of the javascript file. I recommend reading about CSRF tokens.

Important thing is, that if you chosen (like me) the chunking option, this will NOT be the whole file, only the part of it. You can find bigger tutorials on how to handle parted files, but what you need to pay attention for is the qquuid that you will be send in params. This id identifies the file that is being uploaded, and you will need it to determine to what file uploaded part belongs, so you don't mix two files up. Every part is being send by separate post request, so I recommend adding the column like qquuid to the model that is handling the files. For example:

Attachment.new(params[:qqfile], params[:qquuid])

After you save all the files, you can combine them (check the ruby File class to learn how to).

Attachment.where(qquuid: params[:qquuid]).combine_them_all

The above line can be put either in the create action at the end of it, with the condition stating that this is the last part (there are params with the total part number and the index number of the current part, that can be uset to determine that), or in the "finish" action, that you can use if you do

chunking:
    success:
        endpoint: "/upload/finish"

You will have to create a route (same way as shown above) and the action. This action will be triggered after the last part was send. If the file was too small to be parted, this will NOT get triggered, unless you set mandatory to "true".

The last thing, is the json respond. That part is simple, fine uploader expects you to respond (with json) that you received the file and everything went smoothly. If it won't get it, it will assume, something went wrong (you can read more about expected json in the uploader docs). What matters is that in case of failure, it will try to send failed part again (if autoRetry is set to true).

Now, for the view (haml):

#fine-uploader{"data- authenticity-token" => form_authenticity_token}
%script#template-name
    Here goes the template

More about templating you can read in docs, but important thing is, don't use rails form (or simple form) for that. There is a way of connecting forms with fine uploader, but I wasn't able to make it work, and I've had no need of using the form, but if you need it, you can create a hidden field with the generated token, to identify it, and use it instead of qquuid to identify the files. You can provide it in params section the same way, you have provided CSRF token, and use it in the "create" action in the uploads controller.

And that's it. I hope it will help someone.

EDIT: There is an example app made by user Panczo posted in the comments

Community
  • 1
  • 1
ZebThan
  • 255
  • 2
  • 17
  • Hey, great and very detailed answer. Would you be willing to share your full set of rails code as a new repository in the [FineUploader GitHub organization](https://github.com/FineUploader)? – Ray Nicholus Jun 07 '16 at 02:00
  • @RayNicholus Thanks. I would like to share, I just need to write clean and readable example. When I'll have some free time, I'm gonna do it. – ZebThan Jun 07 '16 at 10:15
  • 2
    @ZebThan based on your answer i made example app and put it to gh. Here is this app [rails with reactfineuploader](https://github.com/Panczo/reactfineuploader-example). For the view i used react_webpack_rails gem. – Panczo Dec 16 '16 at 06:43
  • 1
    @Panczo - I took a liberty to add info (and a link) about your app in my answer, so others won't miss it. Hope you don't mind. – ZebThan Dec 20 '16 at 10:22
  • @ZebThan - great. You'd take a look at the code, pull are welcome. – Panczo Dec 22 '16 at 21:33