File uploads, is there a better solution?


#1

Are there really good examples of forms with file uploads with Ember? Currently I have a hacked solution with filepicker.io saving the file to a temp field on the AR model and then using sidekiq to resave the upload to paperclip in the background. I feel a bit like I am trying to look up a cows ass to see a steak instead of just asking the butcher.

How have other people approached the problem of file uploads?


#2

Also, this is a great example of previewing the file upload before it is sent off to the sever: http://chrismeyers.org/2012/06/12/ember-js-handlebars-view-content-inheritance-image-upload-preview-view-object-binding/


#3

Discourse is using jQuery-File-Upload (https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/views/composer_view.js#L275) …

Also this is interesting http://stackoverflow.com/a/13934706/1812872, I think here the app sends you the file in base64, this is cool but may not be a good a idea for large files


#4

My example is non rails specific - I basically subclass an ember view to get the UI hooks and use FormData to do the multipart post


#5

That is interesting. Thank you so much for the reply. Just to make sure I understand the code, the section you referenced is the upload dialog when you are inserting an image in the post text area. Is that correct?

One issue I cannot get past is actually saving a paperclip attachment to a model without the background job. Maybe if I had a separate attachment model with a one to many relationship with the main model, I could at least get rid of the background job that is attaching the uploaded file?

Again, thanks for the help.


#6

Yes, is the uploading dialog in the post text area …

I also think that maybe is easier to have a separated attachment model, like discourse has the Upload model. Also I think other solution could be to upload direct to S3 and with the response create your record like in this example http://pjambet.github.com/blog/direct-upload-to-s3/, but I have never done that and I you will have to translate that to Ember


#7

I’ve used jquery-file-upload after trying all kind of other solutions. It becomes available as a standard file upload in RoR doing it this way.

App.ProjectsEditView = Ember.View.extend({
  didInsertElement: function() {
    self = this;
    $('#fileupload').fileupload({
      url: '/active_data_sets',
      add: function(e, data) {
        data.formData = {project_id: self.get('controller.id'), name: self.get('controller.datasetName')};
        data.submit();
      },
      done: function(e, data) {
        self.get('controller').get('controllers.activedatasetIndex').addDataSet(data.result.data_set);
      }
    });
  }
});

relevant part of the template

 <div class="control-group">
  <label class="control-label">Data bestand</label>
  <div class="controls">
    <input id="fileupload" type="file" name="files[]" multiple>
  </div>
</div>

One part that is not working yet is that it starts straight away, as soon as you selected a file. I would like to start it after the push of a button. If you get that going I would love to know.


#8

I am currently also playing around with the base64 encoded solution. Unfortunately my backend is not 100% playing along and it might not be the best idea with big files.

I would like to have it send like normal form submits work, but within my ember-data save. So that on my backend (php) I can access the file via global $_FILES variable. But haven’t found a solution for that so far.


#9

I think that file has now moved to https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/views/composer/composer_view.js FYI.


#10

I’m using the base64 solution with paperclip. I notice all my files seem to get named ‘data.jpeg’ after upload. Anyone know how to solve this problem?


#11

I also started with base64 uploading, but it becomes quickly a pain when users are uploading files > 5MB on a slow connections as this can block one entire rails worker for multiple minutes.

Our current solution is to let users upload directly to S3 and then send us the resulting url, which allows bigger file uploads and is way faster then the base64 solution.

To achieve this, we have an uploads rest endpoint, which generates the presigned post to the s3 bucket and an ember data model uploading the file.

App.Upload = DS.Model.extend
  fields: DS.attr()
  url: DS.attr()
  contentType: DS.attr()

  upload: (file) ->
    resolver = Ember.RSVP.defer()

    formData = new FormData()
    @get('fields').forEach (key, value) ->
      formData.append(key, value)
    formData.append("file", file)

    $.ajax({
      url: @get('url')
      type: 'POST',
      xhr: ->
        xhr = $.ajaxSettings.xhr()
        xhr.upload.onprogress = (e) ->
          percent = (e.position/ e.totalSize)
          console.log('percent', percent)
        xhr
      fail: (e, data) ->
        resolver.reject()
      success: (result) ->
        resolver.resolve()
      data: formData
      contentType: false
      processData: false
    })

    DS.PromiseObject.create({promise: resolver.promise})

#12

There is also this little Ember library, with drag and drop upload and automatic preview: EmberDroplet


#13

Old topic, but I think the file has moved once again. It’s now at https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/views/composer.js.es6.


#14

Not sure if this topic is dead, but I made a screencast on uploading directly to S3 with ember-uploader. Ember-uploader also supports regular file upload as well. Check it out: http://buildlab.co/u/validkeys/channels/1/episodes/upload-files-directly-to-s3-with-ember