讀取請求本體


如果你要取得請求的本體資訊,可以使用request.body方法,這會取得 StringIO 實例,例如若在 基本 CRDE 程式 中新增書籤,若在控制器的create方法中加上:

print request.body.read(request.content_length)

在發送表單之後,可以看到放在POST本體中的以下訊息:

utf8=%E2%9C%93&authenticity_token=zktCaU6Faf4OQ708RMh24m49bvoMwVWzyrTLwJS8KLg%3D&page%5Btitle%5D=Openhome&
page%5Burl%5D=http%3A%2F%2Fopenhome.cc&page%5Bdescription%5D=caterpillar%27s+learning+notes&commit=Create

若實際上不需要使用到StringIO中讀寫等方法,而只是想一次取得請求本體的原始內容,可以使用request.raw_post方法取得的本體(編碼為ASCII-8BIT字串)。例如以上程式片段可置換為以下,執行結果相同:

print request.raw_post

實際上你查看ActionDispatch::Request的raw_post的原始碼,可以發現也是使用body方法來讀取資料:

# File actionpack/lib/action_dispatch/http/request.rb, line 192
def raw_post
  unless @env.include? 'RAW_POST_DATA'
    @env['RAW_POST_DATA'] = body.read(@env['CONTENT_LENGTH'].to_i)
    body.rewind if body.respond_to?(:rewind)
  end
  @env['RAW_POST_DATA']
end

如果上傳的是檔案,你必須知道如何處理multipart/form-data,原理可以參考 HTTP檔案上傳機制解析 的內容。如果你使用以下的表單選擇一個檔案發送:

<h1>Upload File</h1>  
<%= form_tag "upload", :multipart => true do %>  
    <%= label_tag "file", "File: " %><%= file_field_tag "image" %>
    <br><br>  
    <%= submit_tag "Upload" %>  
<% end %>

這會產生以下的HTML表單:

<h1>Upload File</h1>
<form accept-charset="UTF-8" action="/test/upload" enctype="multipart/form-data" method="post">
    <div style="margin:0;padding:0;display:inline">
        <input name="utf8" type="hidden" value="&#x2713;" />
        <input name="authenticity_token" type="hidden"
               value="zktCaU6Faf4OQ708RMh24m49bvoMwVWzyrTLwJS8KLg=" />
    </div> 
    <label for="file">File: </label><input id="image" name="image" type="file" />
    <br><br> 
    <input name="commit" type="submit" value="Upload" /> 
</form>

注意!為了避免 跨站偽照請求,預設Rails對於非GET的請求,都要求有個authenticity_token參數,如果不想要有這個限制,可以在控制器中消取這個限制:
class SomeController < ApplicationController
  skip_before_filter :verify_authenticity_token
end