檔案上傳下載是用網路必要的功能,不同的需要用不同的方式對應,接下來將以上傳的相關議題,來建立適合單位用的簡易上傳下載功能的網站,並加上簡易的保護功能,來了解 RoR 可以怎麼利用。
最簡易的上傳功能完成
建立一 controller ,這次不用 scaffold 的方式自動建立程式碼:
./script/generate controller upfile index
#vi app/views/upfile/index.html.erb
<%= form_tag({:action=>'save_file'}, :multipart => true)%>
<input type="file" name="filename" />
<input type="submit" name="Upload" value="Upload"/>
</form>
上述的第三行是檔案傳上後,由 RoR 的 save_file 的action 來動作,上傳檔名的參數為 filename。
新增修改 upload 的 layouts ,利用之前其他的 layout 為依據修改
cd app/views/layouts/
cp bibles.html.erb upload.html.erb
編寫一下,將上傳檔案後的動作,並存到指定位置
def save_file
filename = params['filename'].original_filename
filewhere = "/home/ironman/test1/public/upload/#{filename}"
File.open("#{filewhere}", "wb") do |f|
f.write(params['filename'].read)
end
flash[:notice] = "檔案上傳成功,檔名 #{filename}"
redirect_to :action => 'index'
end
連上 http://SITENAME/upfile 就可以看到上傳表單,
因剛才上傳的位置是在 public/upload ,對應到網址是 http://SITENAME/upload/檔名,所以只要看得到檔案所在連結,就可以被下載。
建立簡單的連結列表
編輯 app/controllers/upload/index.rb 如下的內容
def index
@dir = get_local_list
end
def save_file
...
end
private
# 將 上傳檔案的目錄中,將檔名讀成一個 array ,除了「本目錄」及「父目錄」之外
def get_local_list
@dir = []
dir = Dir.open('./public/upload')
dir.sort.each do |d|
if d !~ /^\.*$/
@dir << d
end
end
dir.close
return @dir
end
...
再將 app/views/upfile/index.html.erb 再加入下列的行數,就可以馬上讓網頁上有檔案的連結
<hr noshade width = "90%" color = "red" />
<ul>
<% @dir.each do |file| -%>
<li><%= link_to file, "/upload/#{file}" -%></li>
<% end -%>
</li>
待改進處
建置非常簡單,但會有這些問題:
1.檔案所有人都可看到及下載,這是優點也是缺點。
2.檔名若是中文,會有 Big5、UTF8 及 URL match 不到的問題。
3.若同樣檔名再上傳的話,會覆蓋之前同名的檔案。
4.管理端要去清除較舊的檔案,不是那麼方便,雖然可以用 find 的指令去將幾天前的檔通通刪掉。
接下來將介紹曾經如何以系統管理的方式來解決此問題,以及如何用 RoR 來改寫達到這些需求。