scala + jersey で rails のフォームにファイルアップロード
サンプルはどれが重要なコードが曖昧にする紋切り型を削除しています。
このコードは新規作成のみで、しかも画像以外のデータもアップロード出来ますが
本番では編集画面などの対応、サイズやファイルタイプのバリデーションやエラー表示をしてください。
環境
- ruby 1.8.7
- rails 2.3.11
- java 1.6.0_24
- scala 2.8.1
- jersey 1.8
rails
rails test
cd test
script/generate scaffold test filename:string content_type:string size:integer data:binary
rake db:migrate
script/server
- app/models/test.rb
class Test < ActiveRecord::Base def image=(args) self.size = args.size self.content_type = args.content_type self.filename = args.original_filename self.data = args.read end end
- app/views/tests/new.html.erb
<% form_for(@test, :html => { :multipart => true }) do |f| %> <p><%= f.file_field :image %></p> <p><%= f.submit 'Create' %></p> <% end %> <%= link_to 'Back', tests_path %>
- app/controllers/tests_controller.rb
クラスの一番下に追加
def image @test = Test.find(params[:id]) send_data(@test.data, :type => @test.content_type, :filename => @test.filename) end
- app/views/tests/index.html.erb
ノイズになるので除外したが Show Edit Destroy のリンクはそのままでもOK
<table> <% @tests.each do |test| %> <tr> <td><%=h test.filename %></td> <td><%=h test.content_type %></td> <td><%=h test.size %></td> <td><%= image_tag(url_for(:action => :image, :id => test.id), :size => '100x32') %></td> </tr> <% end %> </table> <br /> <%= link_to 'New test', new_test_path %>
scala
それぞれの jar に CLASSPATH を通す。
apidocs はバージョンが違うので詳しく知りたい人は自分で探してくだしあ。
- jersey-client.jar, jersey-core.jar
http://jersey.java.net/nonav/documentation/latest/user-guide.html#core_client
http://jersey.java.net/nonav/apidocs/latest/jersey/index.html
- mimepull.jar, jersey-multipart.jar
http://jersey.java.net/nonav/documentation/latest/user-guide.html#d4e1825
http://jersey.java.net/nonav/apidocs/1.5/contribs/jersey-multipart/index.html
- test.scala
import com.sun.jersey.api.client.{Client, WebResource} import com.sun.jersey.multipart.FormDataMultiPart import javax.ws.rs.core.MediaType object Test { def main(args: Array[String]) { val file = new java.io.File("/Users/alphaneet/Pictures/test.jpg") // field(送信先のフォームの名前、ファイルパス、ファイルタイプ) val form = new FormDataMultiPart().field("test[image]", file, MediaType.valueOf("image/jpeg")) val wr = Client.create.resource("http://localhost:3000/tests") // post(戻り値の型、フォーム) val ret = wr.`type`(MediaType.MULTIPART_FORM_DATA).post(classOf[String], form) println(ret) } }
画像ファイルのパス や MediaType.valueOf("image/jpeg") は自分の環境に合わせる。
type メソッドは scala の予約語なので バッククォーテーション でくくる。
ブラウザからアップロードする時と違ってファイル名(original_name)が設定されていない。
postのデータに何か追加してやればいいような気がするんですが、いまいち分かりません。
正直 http プロトコルについて詳しく知りません。api叩いてるだけみたいな。
誰か分かったら教えてください。