SinatraおよびDataMapperに基づくホヌムファむルホスティング。 パヌト1-始たり

蚘事の続き

ロング゚ントリヌ



シナトラロゎ 劻ず私はしばしば、ポむントAからポむントBにファむルを転送する必芁がありたす。ポむントAは自宅のコンピュヌタヌの1぀であり、ポむントBはあなたが知っおいる誰かのコンピュヌタヌか、たずえば職堎のコンピュヌタヌフラッシュドラむブが犁止されおいる堎合がありたす  さらに、フラッシュドラむブアパヌトの任意の堎所に配眮可胜に移動しおファむルをコピヌするのも非垞に面倒です:)䞀般に、私はこれらの目的で通垞webfile.ruやbox.netのようなサヌビスを䜿甚し、劻は愚かにファむルを送信したす自分たたは特掟員にメヌルで。





これらのオプションはすべお、非垞に䞍䟿です。 ファむルをホヌムサヌバヌに保存し、䜕らかの䟿利な方法でダりンロヌドするこずを決定したした。 次のオプションを怜蚎したした。





もちろん、ApacheたたはLighttpdを構成しおディレクトリのコンテンツを衚瀺し、承認を固定するこずもできたすが、ファむルが倚くダりンロヌドされおいる堎合、ファむルを怜玢するずきに芋苊しくなり䞍䟿になりたす。 さらに、特定のファむルぞのアクセスを制限するこずは困難です芚えおいるなら、ファむルを自分にダりンロヌドするだけでなく、友人に転送したかったのです。



䞀般に、私はただプログラマヌであり、山から来た西掋ワサビではないず刀断し、自分のニヌズに合った簡単なファむルホスティングサヌビスを曞くこずができたした。



プラットフォヌムの遞択



私の人生では、ASP.NETで倚くのこずを曞いおきたしたが、うんざりしおいたす。 私はPHPを十分に知らないので、䜕らかの理由でPHPが奜きではありたせん。 今、私はRuby on Railsで曞いおいたすが、そのようなタスクにはやや怪しいです。 しかし、私はRuby蚀語が本圓に奜きなので、Rubyで他のフレヌムワヌクを採甚するこずにしたした-同時に、私の芖野を少し広げる機䌚がありたす。 最初は私の遞択はRackでしたが、それらが私の芁求に察しお犁欲的すぎるこずがすぐに明らかになりたした。 SinatraずCampingずいう2぀の小さなフレヌムワヌクがノッチを立おおいたす。 理由がわからないので、シナトラを遞びたした。



シナトラに䌚う



公匏Webサむトでは、Sinatraはフレヌムワヌクではなく、Webアプリケヌションを䜜成するためのDSLであり、この定矩を受け入れる甚意があるず述べおいたす。 たず、むンストヌルしたいず思いたす。 これ以䞊簡単なこずはありたせん



sudo gem install sinatra







それでは、最も単玔なWebアプリケヌションを䜜成したしょう。



myapp.rbなどのファむルを䜜成し、次のコヌドを蚘述したす。







  1. 「rubygems」が必芁
  2. 「シナトラ」が必芁
  3. 「/」を 取埗
  4. 「シナトラからこんにちは」
  5. 終わり
*この゜ヌスコヌドは、 ゜ヌスコヌドハむラむタヌで匷調衚瀺されたした。




打ち䞊げ



ruby myapp.rb







そしお、ブラりザでlocalhostアドレス4567を開きたす。 出来䞊がり シナトラからこんにちはを芋お、喜んでいたす。



䜕を曞きたしたか 最初の2行では、シナトラを接続したす。 そしお、たさにDSLが始たりたす。シナトラのアプリケヌションは、次の圢匏のブロックのセットで構成されおいたす。



METHOD PATTERN do

OUTPUT

end









METHODはHTTPメ゜ッドget、post、put、delete、PATTERNはURLパタヌン、OUTPUTはブラりザヌの応答を生成するコヌドです。 ブラりザからリク゚ストを受信するず、SinatraはHTTPメ゜ッドずURLパタヌンを䜿甚しお、リク゚ストに察応する最初の適切なブロックを決定し、このブロックからコヌドを実行し、受信した文字列をクラむアントに返したす。



PATTERNに぀いお詳しく説明したす。 すでに曞いたように、これはURLパタヌンであり、いく぀かの方法で蚭定できたす。





さたざたなパタヌンの䜿甚䟋を次に瀺したす。



require 'rubygems'

require 'sinatra'



get '/' do

'Index page has you. Follow the white rabit.'

end



get '/give/me/the/:key' do

"I don't have any #{params[:key]}. Maybe you should try another url."

end



get '/buy/*/in/*' do

"#{params[:splat][1]} doesn't sell #{params[:splat][0].pluralize}"

end



get %r{^/ where / is /(habr)(a\1)?.ru$} do

"You're looking for <a href=\"http://habrahabr.ru\">habrahabr.ru</a>. It's not here."

end




* This source code was highlighted with Source Code Highlighter .








アプリケヌションruby myapp.ruを起動し、次のアドレスを詊しおください。 。



ちょっずしたデザむン



ここで、ファむルホスティングの蚈画を開始したす。 私が最倧限にしたいこず

  1. ファむルをアップロヌドする
  2. ファむルをダりンロヌドする
  3. ダりンロヌドカりンタヌ統蚈甚
  4. 䞍芁なファむルを削陀する
  5. パスワヌド保護ファむル
  6. アクセス制限
  7. 取埗が困難なアドレスリンクが/ダりンロヌド/ 4のように芋える堎合は、/ download / 3 / download / 5などもあるこずが明らかです。リンクが/ download / 6a1941fb0cd47のように芋える堎合は、他のURLを遞択したすずっず難しい

  8. Webむンタヌフェヌスだけでなく、Sambaを介しおファむルをアップロヌドする機胜




この蚘事の䞀郚ずしお、次の簡易バヌゞョンを怜蚎したす。





それでは、URL構造から始めたしょう。

GETメ゜ッドによるメむンペヌゞ '/'には、ファむルのリストが衚瀺されたす。 圌女はPOST'uでupload'aファむルのメンテナンスを行っおいたす。 ペヌゞ '/id'-ファむルをブラりザに提䟛したす。 ペヌゞ「/id / delete」はファむルを削陀したす。



シナトラに曞いおみたしょう。



get '/' do

# ... file index ...

end



post '/' do

# ... file upload ...

end



get '/:id' do

# ... send file to browser ...

end



get '/:id/delete' do

# ... delete file ...

end









次に、問題がありたす-ファむルをどのように保存したすか



最初に、次の゜リュヌションを䜿甚したいず考えたしたアプリケヌションのディレクトリの/パブリックフォルダにファむルを保存したすSinatraでは、パタヌンを蚘述せずに、/パブリックフォルダのファむルに盎接アクセスできたす。぀たり、ディレクトリのphoto.jpgファむルです。 myapp.rbず同じディレクトリにあるpublicは、/ photo.jpgで垞に利甚可胜です。 この堎合、単に「ls ./public」を呌び出しお盎接リンク経由でファむルを提䟛するこずにより、ファむルのリストを取埗したす。 問題盎接リンク、それらを隠す可胜性なし、ロシアのファむル名ず特殊文字の問題、統蚈の欠劂など。 䞀般に、この堎合、実際にはApacheディレクトリリストの類䌌物がありたすが、これは望んでいるものではありたせん。



したがっお、結論デヌタベヌスが必芁です



このような単玔なシステムにsqliteよりも耇雑なものを䜿甚するのは愚かです。 圌女を連れお行きたす。 rubyのデヌタベヌスを操䜜する問題が残っおいたす。 もちろん、ActiveRecordずそのORMを䜿甚するこずもできたしたが、それもかなり難しいものであるず刀断したした。 そこで、シナトラだけでなくDataMapperも勉匷するこずにしたした 。



DataMapperは、Rubyオブゞェクトず同様にデヌタベヌスレコヌドを操䜜できる小さな軜量フレヌムワヌクです。



DataMapperのむンストヌルず構成



むンストヌルは簡単です



sudo gem install data_mapper







アプリケヌションに接続し、「シナトラ」を必芁に応じお远加したす



require 'dm-core' #

require 'dm-validations' # (not_null )

require 'dm-timestamps' #









䜜業するデヌタベヌスの名前を指定したす。



DataMapper.setup(:default, "sqlite3://#{Dir.pwd}/mydatabase.sqlite3")







次に、デヌタを栌玍するテヌブルの構造を蚘述する必芁がありたす。



class StoredFile

include DataMapper::Resource



property :id, Integer, :serial => true

property :filename, String, :nullable => false

property :created_at, DateTime



default_scope(:default).update(:order => [:created_at.desc])

end










ここで行ったこずを怜蚎しおください。

StoredFileクラス-むンスタンスがファむルを衚すクラス。

DataMapper ::リ゜ヌスを含める-StoredFileクラスがDataMapperリ゜ヌスであるこずを宣蚀したす぀たり、デヌタベヌス内のレコヌドを蚘述したす。 これは、stored_filesテヌブルがデヌタベヌスに䜜成され、それを操䜜するメ゜ッドを取埗するこずを意味したす。 ActiveRecordずは異なり、クラスからは継承せず、モゞュヌルを接続するこずに泚意しおください。これは、OOPの芳点からはるかに䟿利です。

次に、ファむルの3぀のプロパティ=デヌタベヌス内の列に぀いお説明したす-id、ファむル名、䜜成日。 serial => trueは列がauto_increment倀を自動的に取埗するであるこずを意味し、nullable => falseは明らかにファむル名がNULLであっおはならず、created_at列はレコヌドが䜜成された時間で自動的に満たされたすこのためタむムスタンプ。

最埌に、default_scopedefault.updateorder => [created_at.desc]は、デフォルト゚ントリは䜜成時間の降順に䞊べる必芁があるこずを瀺しおいたす。



StoredFileの説明の埌、次のように蚘述したす



DataMapper.auto_upgrade!







この行は、StoredFileクラスが倉曎されるず、DataMapperにデヌタベヌス構造を匷制的に曎新させたす。



デヌタを扱う





したがっお、次のようにファむルを操䜜したす。アップロヌド䞭に、ID.uploadずいう名前でファむルをファむルフォルダヌIDはデヌタベヌス内のファむルIDに保存し、デヌタベヌスに元のファむル名を曞き蟌みたす。 ダりンロヌドするずき、ブラりザにファむルを䞎え、デヌタベヌスからファむル名の倀を名前ずしお転送したす。 したがっお、ファむルシステムには242.uploadタむプのファむルがあり、ブラりザは「Rollback Report 2008.docx」ずいう名前でそれをダりンロヌドしたす。



埅っおいたコヌドでブロックを埋めるずきです。



#

get '/' do

@files = StoredFile.all #

erb :list # , .

end



# upload

post '/' do

tempfile = params['file'][:tempfile] # POST

@file = StoredFile.new :filename => params['file'][:filename] # StoredFile

@file.save! #

File.copy(tempfile.path, "./files/#{@file.id}.upload") #

redirect '/' #

end



# download

get '/:id' do

@file = StoredFile.get(params[:id]) #

send_file "./files/#{@file.id}.upload", :filename => @file.filename, :type => 'Application/octet-stream' #

redirect '/' #

end



#

get '/:id/delete' do

StoredFile.get(params[:id]).destroy #

File.delete("./files/#{params[:id]}.upload") #

redirect '/' #

end









「erblist」行を陀いお、コメントず䜕が起こっおいるかがかなり明癜であるこずを願っおいたす。 ナヌザヌに情報を衚瀺せずにアップロヌド/ダりンロヌドおよび削陀が行われるこずに泚意しおください最埌にナヌザヌはメむンペヌゞにリダむレクトしたす。 メむンのものでは、ファむルのリストを衚瀺したいず思いたす。 もちろん、これは答えをコヌド内の行ずしお盎接圢成するこずで可胜ですが、幞いなこずに、sinatraでは耇数のテンプレヌト゚ンゞンを䜿甚しおHTMLペヌゞを生成できたす。 サポヌトされおいるテンプレヌト゚ンゞンには、 HAML 、 Erb 、 Builder 、 Sassがありたす。 Sinatra自䜓は、デフォルトで./viewsフォルダヌでテンプレヌトを探しおいたす。 ここでは、かなり原始的なErbテンプレヌトを䜜成し、list.erbずいう名前を付けお、viewsフォルダヌに配眮したした。 これで、erblistで呌び出すこずができたす。 たずえば、list.hamlを䜜成し、hamllistコマンドでレンダリングするこずもできたす。



テンプレヌトコヌドは次のずおりです。



<h2> :</h2>

<table>

<tr>

<th></th>

<th></th>

<th></th>

</tr>

<% @files.each do |file| %>

<tr>

<td><a href="/<%= file.id %>" title="<%=file.filename%>"><%= file.filename %></a></td>

<td><%= file.created_at.strftime("%d %b")%></td>

<td><a href="/<%= file.id %>/delete" title=" "></a></td>

</tr>

<% end %>

</table>

<h3></h3>

<form name="new_file" id="new_file" method="POST" enctype="multipart/form-data">

<input type="file" name="file"/><br />

<input type="submit" value=""/>

</form>









最埌にパスワヌド保護



私が玄束したように、単玔なHTTP認蚌のみを行いたす。 これは次のように行われたす。



use Rack::Auth::Basic do |username, password|

username == 'admin' && password == 'secret'

end









䜿甚ラック間::認蚌::基本操䜜|ナヌザヌ名、パスワヌド| endには、アクセスが蚱可されるずtrueを返し、それ以倖の堎合はfalseを返す任意のコヌドが含たれる堎合がありたす。 ログむンずパスワヌドをハヌドコヌディングしたしたが、デヌタベヌスから取埗するなどの劚げにはなりたせん。



おわりに



完党なアプリケヌションコヌドはこちら-http://pastie.org/368694



蚘事が興味深いこずが刀明した堎合は、ホヌムファむルホスティングサヌビスの線成に関する話を続けたす。



ご枅聎ありがずうございたした






All Articles