Using ng-file-upload with Rails media to upload multiple files

I am trying to combine ng-file-upload and carrierwave to upload multiple files, but the server side controller only gets one file (the last element of the selected files).

Client side ( link )

HTML

<button type="file" ng-model="files" ngf-select ngf-multiple="true">Upload</button> 

Js

 var upload = function (files, content) { return Upload.upload({ url: 'MY_CONTROLLER_URL', file: files, // files is an array of multiple files fields: { 'MY_KEY': 'MY_CONTENT' } }).progress(function (evt) { var progressPercentage = parseInt(100.0 * evt.loaded / evt.total); console.log('progress: ' + progressPercentage + '% ' + evt.config.file.name); }).success(function (data, status, headers, config) { console.log('files ' + config.file.name + ' uploaded. Response: ' + data); }).error(function (data, status, headers, config) { console.log('error status: ' + status); }); }; 

console.log(files) prints an array of [File, File, ...] (Browser: FireFox). Thus, on the client side, it receives the selected files. The GitHub ng-file-upload page says that it supports an array of files for html5 .

Server side ( link )

posts_controller.rb

 def create @post = Post.new(post_params) @post.attaches = params[:file] @post.save render json: @post end private def post_params params.require(:post).permit(:content, :file) end 

where @post.attaches are message attachments, and params[:file] sent from the client side with the file parameter in Upload.upload .

I want to save an array of files in @post.attaches , but params[:file] contains only one file from the selected files. puts params[:file] Prints:

 #<ActionDispatch::Http::UploadedFile:0x007fddd1550300 @tempfile=#<Tempfile:/tmp/RackMultipart20150812-2754-vchvln.jpg>, @original_filename="Black-Metal-Gear-Rising-Wallpaper.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"file\"; filename=\"Black-Metal-Gear-Rising-Wallpaper.jpg\"\r\nContent-Type: image/jpeg\r\n"> 

This shows that there is only one file in params[:file] . I am not sure if there is anything wrong with using this parameter.

How can I solve this problem?


Below is my post.rb model and attach_uploader.rb (created by carrierwave ) for reference:

post.rb

 class Post < ActiveRecord::Base mount_uploaders :attaches, AttachUploader end 

attach_uploader.rb

 class AttachUploader < CarrierWave::Uploader::Base storage :file def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end end 

and @post.attaches is added to posts database

 rails g migration add_attaches_to_posts attaches:json 
+7
angularjs ruby-on-rails ng-file-upload carrierwave
source share
1 answer

I finally found a way to solve my problem. Thanks for carrierwave and danialfarid awesome ng-file-upload .

My problem was that I could not send all the selected files. My decision was

 var upload = function (files) { var names = []; for (var i = 0; i < files.length; ++i) names.push(files[i].name); return Upload.upload({ url: '/api/v1/posts', file: files, fileFormDataName: names }); } 

Then in my rails controller.rb

 file_arr = params.values.find_all { |value| value.class == ActionDispatch::Http::UploadedFile } if @post.save unless file_arr.empty? file_arr.each { |attach| @attach = Attach.new @attach.filename = attach @attach.attachable = @post @attach.save } end render json: @post end 

I created an array to store all my files from params .

I tried using the mount_uploaders carrierwave column to store an array of files, but that didn't work. So I create a file table called attaches to store my files

 class CreateAttaches < ActiveRecord::Migration def change create_table :attaches do |t| t.string :filename t.references :attachable, polymorphic: true t.timestamps null: false end end end 

where attachable used to store the identifier and type of message. (Here my attachments refer to some posts on my forum.)


Below are some configuration information if necessary.

attach.rb (model)

 class Attach < ActiveRecord::Base mount_uploader :filename, AttachUploader belongs_to :attachable, :polymorphic => true end 

post.rb (model)

 class Post < ActiveRecord::Base has_many :attaches, as: :attachable, dependent: :destroy end 

post_serializer.rb

 class PostSerializer < ActiveModel::Serializer has_many :attaches end 

attach_serializer.rb

 class AttachSerializer < ActiveModel::Serializer attributes :url, :name def url object.filename.url end def name object.filename_identifier end end 

Then in html file can have line code

 <div ng-repeat="attach in post.attaches"> <img ng-src="{{attach.url}}" type="file" height="180" width="320" accept="image/*"/> <a target="_self" ng-show="attach.url" href="{{attach.url}}" download="{{attach.name}}">{{attach.name}}<p></p></a> </div> 

where my default images are used for images.

+1
source share

All Articles