讀取 http 請求中的大數據, 每次讀取必定的體積.socket
Plug.Conn.read_body/2
@spec read_body(t(), Keyword.t()) :: {:ok, binary(), t()} | {:more, binary(), t()} | {:error, term()}
此函數有三個配置選項, 根據文檔, length:
表示這一次函數調用讀取數據的長度; read_length:
表示從底層的 socket 每次讀取數據的長度; read_timeout:
表示從底層的 socket 每次讀的 timeout.函數
看起來很不錯, 但其實只能起到一個大概的做用, 不能相信它返回的數據必定小於某個大小.測試
咱們對不一樣的配置選項進行測試:大數據
# defp print_size(body, config), do: # IO.inspect({byte_size(body), config}) body = :binary.copy("abcdefghij", 100_000) assert {:more, body, conn} = read_body(conn, length: 0, read_length: 1_000) print_size(body, {0, 1000}) assert {:more, body, conn} = read_body(conn, length: 5_000, read_length: 1_000) print_size(body, {5000, 1000}) assert {:more, body, conn} = read_body(conn, length: 20_000, read_length: 1_000) print_size(body, {20_000, 1000}) assert {:ok, body, conn} = read_body(conn, length: 2_000_000) print_size(body, {2_000_000, nil})
第一次結果:code
{2766, {0, 1000}} {5840, {5000, 1000}} {20440, {20000, 1000}} {970954, {2000000, nil}}
第二次結果:文檔
{2766, {0, 1000}} {8760, {5000, 1000}} {21900, {20000, 1000}} {966574, {2000000, nil}}
注意到每次讀取到的數額都會比咱們設置的 length 大, 甚至大於 length + read_length. 因此這個配置是不可靠的, 若是想要精確地按長度處理 body 內的數據, 仍是須要進行進一步的分割操做.class