輕松掌握Ruby on Rails上傳圖片實現技巧
Ruby on Rails作為一種WEB開發框架,擁有許多關于網站建設的功能,幫助我們簡單完善自身的網站開發。比如圖片的上傳等。下面我們就為大家介紹Ruby on Rails上傳圖片的相關技巧。#t#
我們希望當新增留言的時候,允許用戶上傳圖片,并能判斷上傳文件的類型是否為圖片和文件是否過大。這在Rails中不難做到,不需要使用任何插件,只用十分簡潔的代碼即可實現Ruby on Rails上傳圖片!這的確是一件讓程序員愉快的事情。
修改/app/views/message路徑下的new.rhtml視圖文件。修改后的代碼如下:
- < table valign="top" width="100%"
border="0" cellspacing="0" cellpadding="0"> - < tr>
- < td>
- < center>
- < %= error_messages_for 'message' %>
- < /center>
- < !-- 將multipart選項設置為true,允許上傳文件 -->
- < %= start_form_tag ({ :action =>
'create', :id => @message }, :multipart => true) %> - < table align="center" width="400"
border="0" cellpadding="0" cellspacing="0" - bgcolor="#BFCAE6">
- < tr>
- < td colspan="2" id="title">新增留言< /td>
- < /tr>
- < tr>
- < td width="15%">< b>標題< /b>< /td>
- < td >< %= text_field('message',
'title', :size => "30")%>< /td> - < /tr>
- < tr>
- < td width="15%">< b>內容< /b>< /td>
- < td >< %= text_area 'message',
'detail', "cols" => 40, "rows" => 10 %>< /td> - < /tr>
- < tr>
- < td width="15%">< b>貼圖< /b>< /td>
- < !-- 調用file_field幫助方法,生成一個文件域 -->
- < td >< %= file_field 'message', 'picture' %>< /td>
- < /tr>
- < tr>
- < td colspan="2" align="center"><
%= submit_tag '提交' %>< /td> - < /tr>
- < /table>
- < %= end_form_tag %>
- < /td>
- < /tr>
- < /table>
上面的Ruby on Rails上傳圖片代碼在start_form_tag幫助方法中指定multipart的選項值為true,使得該表單能夠發送文件數據。并且,通過調用file_field幫助方法,生成了一個文件域。這里的picture屬性只是個虛擬屬性,因為在數據庫的messages表中并不存在這個屬性。這需要我們對這個虛擬屬性做一些處理,使之對應messages表中的真實屬性。具體實現方式下面會有詳細介紹。
上面的表單是沒有為留言時間設計表單域的,因為我們可以通過更簡便的方式來為Message對象的這個屬性賦值:messages表中表示留言時間的字段名為created_at,數據類型設計為timestamp,這樣,當保存一條Message對象對應的記錄時,Rails就會自動將當前時間賦值給created_at列,而不需要我們手動賦值。
在message_controller.rb控制器文件中,需要修改create方法,修改后該方法的Ruby on Rails上傳圖片代碼片段如下。
- def create
- # 查找出當前留言的User對象
- user=User.find(session[:user_id])
- # 將該User對象賦值給參數中
Message對象的user屬性- params[:message][:user]=user
- # 構造一個Message對象,
并使用message參數來初始化該對象- @message = Message.new(params[:message])
- # 如果Message對象能成功保存進數據庫
- if @message.save
- flash[:notice] = '新增留言成功!'
- # 重定向到list Action
- redirect_to :action => 'list'
- else
- # 提交new Action
- render :action => 'new'
- end
- end
在create方法的定義中,前面兩句代碼是scaffold生成的默認代碼中所沒有的。這是因為user_id是messages表參照users表的外鍵列,scaffold不會自動生成對外鍵列的操作。所以,我們需要根據session[:user_id]來查找出留言的User對象,并把該對象賦值給表單參數中的Message對象,作為它的一個user屬性。這樣,當Message對象調用save方法保存進數據庫的時候,會讓該Messge對象對應的數據行參照到該User實例對應的數據行。
在Message Model文件中,重定義一個picture=方法。因為我們的new.rhtml視圖文件中有一個picture表單域,當提交表單后控制器將發送一個message[:picture]的請求參數,這個請求參數將要求Message類里包含一個picture=方法,該方法用于接受message[:picture]請求參數。
picture=方法負責把message[:picture]請求參數(這個請求參數值是一個文件對象,里面包含了非常豐富的信息)解析出來。下面是picture=方法的代碼:
- # 提供picture=方法,將一個picture
的表單域設置成Message對象的多個屬性- def picture=(picture_field)
- transaction do
- # 如果用戶上傳了圖片
- if picture_field.size>0 then
- # @picture_size為上傳圖片的文件大小
- @picture_size=picture_field.size
- # @picture_type為上傳圖片的文件類型
- @picture_type=picture_field.content_type.chomp
- # 設置Message對象的picture_content_type屬性
- self.picture_content_type =@picture_type
- # 設置Message對象的picture_data屬性
- self.picture_data = picture_field.read
- end
- end
- end
提供了picture=方法之后,我們就將message[:picture]請求參數與messages表中的真實屬性picture_content_type和picture_data對應起來了。
在Ruby on Rails上傳圖片方面,Rails處理得很好,表單中的文件域參數值不再是一個簡單的類型值,而是已經被包裝成一個文件對象,它也有size,content_type和read方法,直接調用這些方法,即可返回這個文件對象的大小、文件類型和包含的二進制數據。
當用戶添加一條留言時,我們需要對留言對象進行模型校驗,這可以通過在message.rb模型文件中重寫validate方法來實現。代碼如下:
- def validate
- # 驗證title不能為空
- errors.add("", "標題不能為空") if title.empty?
- # 驗證detail不能為空
- errors.add("", "內容不能為空") if detail.empty?
- # 下面校驗上傳的圖片
- if @picture_type != nil
- # 校驗上傳圖片的文件類型
- errors.add("", "貼圖不是合法的圖片文件")
unless @picture_type =~ /^image/- end
- if @picture_size != nil
- # 校驗上傳圖片的文件大小
- errors.add("", "貼圖文件太大,應不能超過50
KB") if @picture_size > MAX_IMAGE_SIZE- end
- end
在上面的Ruby on Rails上傳圖片代碼中,我們校驗留言標題、留言內容的值不能為空,上傳的文件類型必須是圖片形式,并且文件大小不能超過允許上傳的***圖片值(MAX_IMAGE_SIZE為允許上傳的***圖片值)。


















