Railsで複数画像アップロードをする
Rails + Paperclipで画像アップロードが出来ますが、複数の画像を一気にアップロードしたい場合があると思います。その場合はjquery-upload-railsを使うといいと思います。
使い方はgithubページに書いてあるので分かると思いますが、一点注意が必要です。
以下順に手順を書いていきます
1.Gemfileに追記してbundle installする
gem "jquery-fileupload-rails"
$ bundle install --path vendor/bundle
2.複数画像アップロード用のviewの追加
こちらはサンプルとしてみたページのソースを、使わせてもらいました。
1 <div class="container"> 2 <h2>Upload file</h2> 3 <%= form_for @photo, :html => { :multipart => true, :id => "fileupload" } do |f| %> 4 <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload --> 5 アルバム選択:<%= f.select "album_id", options_from_collection_for_select(@albums,"id","title") %> | <%= link_to 'アルバム作成', {controller: " albums", action: "new", from_url: 'photo'} %><br/> 6 <%= f.label :title %>:<%= f.text_field :title %><br/> 7 <%= f.label :description %>:<%= f.text_area :description, :size => "40x20" %><br/> 8 <div class="row fileupload-buttonbar"> 9 <div class="span7"> 10 <!-- The fileinput-button span is used to style the file input field as button --> 11 <span class="btn btn-success fileinput-button"> 12 <i class="icon-plus icon-white"></i> 13 <span>Add files...</span> 14 <%= f.file_field :photo %> 15 </span> 16 <button type="submit" class="btn btn-primary start"> 17 <i class="icon-upload icon-white"></i> 18 <span>Start upload</span> 19 </button> 20 <button type="reset" class="btn btn-warning cancel"> 21 <i class="icon-ban-circle icon-white"></i> 22 <span>Cancel upload</span> 23 </button> 24 <button type="button" class="btn btn-danger delete"> 25 <i class="icon-trash icon-white"></i> 26 <span>Delete</span> 27 </button> 28 <input type="checkbox" class="toggle"> 29 </div> 30 <div class="span5"> 31 <!-- The global progress bar --> 32 <div class="progress progress-success progress-striped active fade"> 33 <div class="bar" style="width:0%;"></div> 34 </div> 35 </div> 36 </div> 37 <!-- The loading indicator is shown during image processing --> 38 <div class="fileupload-loading"></div> 39 <br> 40 <!-- The table listing the files available for upload/download --> 41 <table class="table table-striped"><tbody class="files" data-toggle="modal-gallery" data-target="#modal-gallery"></tbody> 42 </table> 43 <% end %> 44 45 </div> 46 <script> 47 var fileUploadErrors = { 48 maxFileSize: 'File is too big', 49 minFileSize: 'File is too small', 50 acceptFileTypes: 'Filetype not allowed', 51 maxNumberOfFiles: 'Max number of files exceeded', 52 uploadedBytes: 'Uploaded bytes exceed file size', 53 emptyResult: 'Empty file upload result' 54 }; 55 </script> 56 57 <!-- The template to display files available for upload --> 58 <script id="template-upload" type="text/x-tmpl"> 59 {% for (var i=0, file; file=o.files[i]; i++) { %} 60 <tr class="template-upload fade"> 61 <td class="preview"><span class="fade"></span></td> 62 <td class="name"><span>{%=file.name%}</span></td> 63 <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td> 64 {% if (file.error) { %} 65 <td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td> 66 {% } else if (o.files.valid && !i) { %} 67 <td> 68 <div class="progress progress-success progress-striped active"><div class="bar" style="width:0%;"></div></div> 69 </td> 70 <td class="start">{% if (!o.options.autoUpload) { %} 71 <button class="btn btn-primary"> 72 <i class="icon-upload icon-white"></i> 73 <span>{%=locale.fileupload.start%}</span> 74 </button> 75 {% } %}</td> 76 {% } else { %} 77 <td colspan="2"></td> 78 {% } %} 79 <td class="cancel">{% if (!i) { %} 80 <button class="btn btn-warning"> 81 <i class="icon-ban-circle icon-white"></i> 82 <span>{%=locale.fileupload.cancel%}</span> 83 </button> 84 {% } %}</td> 85 </tr> 86 {% } %} 87 </script> 88 <!-- The template to display files available for download --> 89 <script id="template-download" type="text/x-tmpl"> 90 {% for (var i=0, file; file=o.files[i]; i++) { %} 91 <tr class="template-download fade"> 92 {% if (file.error) { %} 93 <td></td> 94 <td class="name"><span>{%=file.name%}</span></td> 95 <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td> 96 <td class="error" colspan="2"><span class="label label-important">{%=locale.fileupload.error%}</span> {%=locale.fileupload.errors[file.error] || file.error%}</td> 97 {% } else { %} 98 <td class="preview">{% if (file.thumbnail_url) { %} 99 <a href="{%=file.url%}" title="{%=file.name%}" rel="gallery" download="{%=file.name%}"><img src="{%=file.thumbnail_url%}"></a> 100 {% } %}</td> 101 <td class="name"> 102 <a href="{%=file.url%}" title="{%=file.name%}" rel="{%=file.thumbnail_url&&'gallery'%}" download="{%=file.name%}">{%=file.name%}</a> 103 </td> 104 <td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td> 105 <td colspan="2"></td> 106 {% } %} 107 <td class="delete"> 108 <button class="btn btn-danger" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}"> 109 <i class="icon-trash icon-white"></i> 110 <span>{%=locale.fileupload.destroy%}</span> 111 </button> 112 <input type="checkbox" name="delete" value="1"> 113 </td> 114 </tr> 115 {% } %} 116 </script> 117 118 <script type="text/javascript" charset="utf-8"> 119 $(function () { 120 // Initialize the jQuery File Upload widget: 121 $('#fileupload').fileupload(); 122 // 123 // Load existing files: 124 $.getJSON($('#fileupload').prop('action'), function (files) { 125 var fu = $('#fileupload').data('blueimpFileupload'), 126 template; 127 fu._adjustMaxNumberOfFiles(-files.length); 128 console.log(files); 129 template = fu._renderDownload(files) 130 .appendTo($('#fileupload .files')); 131 // Force reflow: 132 fu._reflow = fu._transition && template.length && 133 template[0].offsetWidth; 134 template.addClass('in'); 135 $('#loading').remove(); 136 }); 137 138 }); 139 </script>
今回はpaperclipでphotoモデルのデータ登録し、画像をアップロードしています。
3.続いてcontrollerです。2.で作成したviewを表示するメソッドを追加します。
# Get multi_upload def multi_upload @photo = Photo.new @albums = Album.where(user_id: session[:user_id]).latest respond_to do |format| format.html format.json { head :ok } end end
今回はmulti_uploadという名前で定義します。
4.最後にcreateメソッドに追記します。
今回画像同時アップロード時にコントローラのcreateメソッドを画像の数分呼びますが、そのcreateメソッドの戻り値でjson形式でデータを決まったフォーマットで渡さないとアップロードが正常に完了してもエラーメッセージが表示されてしまいます。
参照
# POST /photos # POST /photos.json def create @photo = Photo.new(photo_params) @photo.user_id = current_user.id respond_to do |format| if @photo.save format.html { redirect_to @photo, notice: 'Photo was successfully created.' } format.json { render json: { :files => [@photo.photo.url(:thumb)]}, status: :created, location: @photo } else format.html { render action: "new" } format.json { render json: @photo.errors, status: :unprocessable_entity } end end end
以上で複数画像をアップロードできるはずです。