2008-09-29
■ちょっと変更
久しぶりに日記。本業が忙しすぎて、何もできず。
少しだけファイルのアップダウンの処理を変更。
サーバに保存するファイル名がURLエンコードになるのはいやだったので、
レコードのIDで保存するように変更。
def create upload = params[:doc] doc = Document.create( :filename=>upload['file'].original_filename ) path = "/files/" +doc.id.to_s; File.open( path, "wb") { |f| f.write( upload['file'].read ) } end def download doc = Document.find(params[:id]) path = "/files/" + doc.id.to_s; send_file(path, :filename => filename_for_content_disposition(doc.filename)) end
FireFoxを入れてうまくいくか試した。OKだね。IEだとやっぱりURLエンコードのファイル名で
オープンされてしまう。
いろいろサイトを調べるとiconvを使っている人が多い。
今度これを試してみよう。
2008-09-22
■漢字ファイルのダウンロード
漢字ファイルのダウンロードでエラーになる部分は、redmineを参考にしてみた。
application.rbのメソッド
def filename_for_content_disposition(name) request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name end
HTML素人なので、全部調べた。
"env['HTTP_USER_AGENT']"は、ブラウザの情報が入ってる。
IE7は次の情報を送ってくる。
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)
で、"ERB::Util.url_encode(name)"の部分は、URLエンコードってやつで、
%付きの文字列にしてくれる。これで漢字の部分は"%E6%BC%A2%E5…"に変換される。
これでファイルへの保存とsend_fileに引き渡すときに変換してやる。
こんな感じ。
def create upload = params[:doc] path = "/files/" + filename_for_content_disposition(upload['file'].original_filename) File.open( path, "wb") { |f| f.write( upload['file'].read ) } Document.create( :filename=>upload['file'].original_filename ) end def download document = Document.find(params[:id]) path = "/files/" + filename_for_content_disposition(document.filename) send_file(path) end
いくつか問題あり。
・ファイルの保存ダイアログの確認表示でファイル名に空白があると%20となる。
・実際に保存されたファイル名は%付きなので何が何だかわからない。
一応、うまくいった。
これで思ったのは、IE以外も試さないといけないということ。
FireFoxとかで試してみるか。
2008-09-18
■また漢字に関するエラー
Railsでファイルのダウンロードができた〜…と思っていたが、
なんだかうまくいかない状況がある。しかも2つ。
一つ目は、ファイルのダウンロードで、日本語ファイル名を使用すると
Cannot read file /files/漢字ファイル.txt
と表示される。アップロードはできたのに?ダウンロードはできないの?
もう一つはWEBrickのエラー。
大きなファイルをダウンロードしようとするとWEBrickのコンソールにエラーが出る。
IOError。これは何となくわかるけど、続く文字が文字化けしてる。
これもよくわからなかったので、試しにglassfishを使ってみることにした。
(最近NetBeans6.5をBetaからDevelopmentバージョンに変えたついでに入れた)。
プロジェクトのプロパティでWEBrickからglassfishに変更。
サーバは動いたんだけど…何にもWEBページ出ません。
さてどれから解決していこう…タイムリミット。明日調べます。
2008-09-17
■ファイルのダウンロード
前回の続きで、モデルdocumentを作成する。項目はファイル名(filename:string)。
NetBeansだと、プロジェクトの「生成...」からmodelを選択して、引数に
document filename:string
を入力する。
データベースのマイグレーションも「現在のバージョンへ」を選択し作成。
ビューはこんな感じで(index.html.rb)。
<table>
<tr>
<th>ファイル名</th>
</tr>
<% @documents.each do |document| %>
<tr>
<td><%= link_to( h(document.filename),
{:controller=>"document",:action=>"download",:id=>document.id } )%>
</td>
</tr>
<% end %>
</table>
ローカルホストの/document/indexを参照するとファイル名の一覧が表示される。
ダウンロードするメソッド「download」をコントローラに追加する。
def download document = Document.find(params[:id]) path = "/files/" + document.filename send_file(path) end
テーブルdocumentのfilenameにファイル名を入れ、filesフォルダ下に実際のファイルを保存する。
一覧にはテーブルのfilenameを表示し、ダウンロードの時にfilesフォルダ下のファイルを送る仕組みだ。
これでファイルのダウンロードはできたぞ。
2008-09-16
■ようやく簡単なファイルのアップロード
まずはRailsのビューとコントローラだけでファイルのアップロードを作成
ビューの方はこんな感じ(new.html.erb)
<% form_tag({:controller => 'document', :action => 'create'}, :multipart => true) do %>
<%= file_field :doc, 'file' %><br/>
<%= submit_tag '登録' %>
<% end %>
でコントローラの方は、こんな感じ(document.controller.rb)
def new end def create upload = params[:doc] path = "/files/" + upload['file'].original_filename File.open( path, "wb") { |f| f.write( upload['file'].read ) } end
最初にコントローラdocumentとnewメソッド、createメソッドを作って
上記のコードを入れる。ローカルホストの/document/newにアクセスすると、
ファイルアップロードの画面が出るので、ファイル名を入力し、登録ボタンを
押すとプロジェクトのfilesフォルダ下にファイルが作成される。
(プロジェクトフォルダの下にfllesフォルダを事前に作成しておく)
たったこれだけで完成なのに1週間悩んだ。
2008-09-09
■scaffoldから作ると大変
form_forとかのリファレンスを読むと、いろんな書き方があって、何がなんだか。
しかもscaffoldから生成されたコードはシンプルなんだけど、それが余計にわからなくなってきた。
やはり地道にコツコツと勉強すべし。
scaffoldを使用せずに、モデルを作り、コントローラとビューを作り、…という具合にやっていこう。
ついでに途中で調べたrespond_toの覚書。要するにrespond_toは、mimeタイプ(htmlとかxmlとか)を
見て、それに合わせた描画を指定できる。mimeタイプ毎に処理を分けずに済むということらしい。
scaffoldの出力は、respond_toで処理されている。メソッドの注釈を見ればアクセス方法は
なんとなくわかった。
2008-09-08
■form_forとform_tag
ファイルのアップロード方法を勉強する上でわかったこと。
HTMLで入力したものをサーバに送るのはformフィールドで記述する。
Railsではそれを簡単に記述するために「ヘルパー」を用意している。
formフィールド用のヘルパーの代表的なものにはform_forとform_tagがある。
form_forはモデルに存在する項目を入力する場合、簡単に書くことができる。
form_tagはモデルに存在しない項目を入力する場合に使用する。
scaffoldで生成されたビューはform_forを使用する。
書き方が全然違うのでもうちょっと勉強しないといけないなあ。