× {{alert.msg}} Never ask again
Get notified about new tutorials RECEIVE NEW TUTORIALS

Upload video files with Rails, paperclip and jquery-upload-file library

Alfredo Motta
May 23, 2015
<p>Rails does not provide many defaults when dealing with AJAX uploads by means of external JS libraries. In this Quick Tip we want to use https://github.com/hayageek/jquery-upload-file to upload a video to a Rails backend.<br> <br> The view looks like follow:</p> <pre><code class="language-ruby">= form_for @movie do |m| = m.text_field :title, placeholder: 'Title' = m.text_area :description, placeholder: 'Description', rows: '3' = m.file_field :video = m.submit 'Upload', id: 'fileUpload', data: { disable_with: 'Uploading' } </code></pre> <p>As you can imagine there is a <em>Movie</em> model in the backend ready to be created.<br> In the submit button notice the:</p> <pre><code class="language-ruby">data: { disable_with: 'Uploading' }</code></pre> <p>This way the browser will not submit our request, but we will rely on jquery-upload-file.</p> <p>On the JS code this is what we need now:</p> <pre><code class="language-javascript">$(document).ready(function() { var uploadObj = $("#movie_video").uploadFile({ url: "/movies", multiple: false, fileName: "movie[video]", autoSubmit: false, formData: { "movie[title]": $('#movie_title').text(), "movie[description]": $('#movie_description').text() }, onSuccess:function(files,data,xhr) { window.location.href = data.to; } }); $("#fileUpload").click(function(e) { e.preventDefault(); $.rails.disableFormElements($($.rails.formSubmitSelector)); uploadObj.startUpload(); }); });</code></pre> <p>As you can see the javascript code is populating the <em>formData </em>with the form parameters which will arrive to the backend together with the video. When the user click the submit button we do the following: (i) we avoid the default form submission with e.preventDefault() and (ii) we disable the button for multiple submissions with $.rails.disableFormElements($($.rails.formSubmitSelector));</p> <p>The create action in the controller looks as follows:</p> <pre><code class="language-ruby"> def create @movie = Movie.create(movie_params) @movie.user = current_user if @movie.save render :json =&gt; { :status =&gt; :redirect, :to =&gt; movie_path(@movie.id) }.to_json else render 'new' end end</code></pre> <p>The create action is taking the parameters from the request and attaching the video to the model using the paperclip and paperclip-av-transcoder gem.</p> <p>This is an example of parameters that we receive in the controller:</p> <pre><code class="language-ruby">[1] pry(#&lt;MoviesController&gt;)&gt; params =&gt; {"movie"=&gt; {"video"=&gt; #&lt;ActionDispatch::Http::UploadedFile:0x007fb1d00f31b8 @content_type="video/quicktime", @headers="Content-Disposition: form-data; name=\"movie[video]\"; filename=\"TestVideo.mov\"\r\nContent-Type: video/quicktime\r\n", @original_filename="TestVideo.mov", @tempfile=#&lt;File:/var/folders/fj/68q9tlrj4h30xpc_xxhbb4h80000gn/T/RackMultipart20150523-36995-mrhxma.mov&gt;&gt;, "title"=&gt;"", "description"=&gt;""}, "controller"=&gt;"movies", "action"=&gt;"create"}</code></pre> <p>The model will have the following (magic) code to attach the video:</p> <pre><code class="language-ruby"> has_attached_file :video, styles: { :medium =&gt; { :geometry =&gt; "640x480", :format =&gt; 'mp4' }, :thumb =&gt; { :geometry =&gt; "160x120", :format =&gt; 'jpeg', :time =&gt; 10} }, :processors =&gt; [:transcoder]</code></pre> <p>Finally the controller simply returns a JSON object with the url for the next page where the user should be redirected after the upload is done.</p> <p>The JSON is picked up by onSuccess() callback of the the jquery-upload library. At this point a simple window.location.href will do the trick.</p> <p>Hope it is useful,<br> Enjoy</p> <p> </p>
comments powered by Disqus