ElixirからCowboy 1.0と2.0を使ってみる Part 10

# はじめに
ElixirにてCowboyを直接動かすための記事となります。
[前回](http://qiita.com/hayabusa333/items/984d87b4a56fea1eb852)の記事では、リクエストに含まれているcookie情報の確認を行う方法を実装しました。
今回はCowboyのドキュメントに記載されている、 Sending files のメソッドについて記載していきます。

[Cowboy1.0のサンプルコードはこちらになります](https://github.com/hayabusa333/elixir_cowboy_example/tree/send_file_cowboy)

[Cowboy2.0のサンプルコードはこちらになります](https://github.com/hayabusa333/elixir_cowboy_example/tree/send_file_cowboy_two_pre4)

# バージョン
使用した言語やライブラリのバージョンは下記となります。

## cowboy 1.0のバージョン
|  | Version |
|:-----------|--------:|
| Elixir | 1.3.2 |
| Erlang | 19.2 |
| Cowboy | 1.0.4 |

## cowboy 2.0のバージョン
|  | Version |
|:-----------|--------:|
| Elixir | 1.3.2 |
| Erlang | 19.2 |
| Cowboy | 2.0.0-pre4 |

# ファイルの送信

今回はファイルの送信処理となります。
以前の記事から何度も行ってはありますが、下記の`sendfile`メソッドを使用するとディスクからファイルを読み込んでからおくるのではなく、直接ファイルを送信してくれるようです。

## cowboy 1.0の場合

``` elixir:lib/elixir_cowboy_example.ex
    routes = [
      {"/", ElixirCowboyExample.Handler, []},
      # Add it
      {"/sendfile", ElixirCowboyExample.SendFileHandler, []},
      {"/cookie", ElixirCowboyExample.CookieHandler, []},
      {"/upload", ElixirCowboyExample.UploadHandler, []},
      {"/dynamic", ElixirCowboyExample.DynamicPageHandler, []},
      {"/json", ElixirCowboyExample.JsonHandler, []},
      {"/:html", ElixirCowboyExample.Handler, []},
      {"/priv/static/js/:javascript", ElixirCowboyExample.JavascriptHandler, []},
      {"/priv/static/css/:css", ElixirCowboyExample.CssHandler, []},
      {"/priv/static/image/[...]", :cowboy_static, {:priv_dir, :elixir_cowboy_example, "static/image"}}
    ]
```

``` elixir:lib/elixir_cowboy_example/send_file_handler.ex
defmodule ElixirCowboyExample.SendFileHandler do
  def init({:tcp, :http}, req, opts) do
    {:ok, req, opts}
  end

  def handle(req, state) do

     # fileの指定
     path = "priv/static/image/button.png"

     # fileのサイズを取得
     %File.Stat{size: file_size} = File.stat!(path)

     # bodyにて送る際のメソッドを指定
     body_fun = fn(socket, transport) -> 
                  transport.sendfile(socket, path)
                end

     headers = [ {"content-type", "image/png"} ]

     # fileの送信
     {:ok, req} = :cowboy_req.reply(200, headers, :cowboy_req.set_resp_body_fun(file_size, body_fun, req))

     {:ok, req, state}
  end

  def terminate(_reason, _req, _state) do
    :ok
  end
end
```

## cowboy 2.0の場合

``` elixir:lib/elixir_cowboy_example.ex
    routes = [
      {"/", ElixirCowboyExample.Handler, []},
      # Add it
      {"/sendfile", ElixirCowboyExample.SendFileHandler, []},
      {"/cookie", ElixirCowboyExample.CookieHandler, []},
      {"/upload", ElixirCowboyExample.UploadHandler, []},
      {"/dynamic", ElixirCowboyExample.DynamicPageHandler, []},
      {"/json", ElixirCowboyExample.JsonHandler, []},
      {"/:html", ElixirCowboyExample.Handler, []},
      {"/priv/static/js/:javascript", ElixirCowboyExample.JavascriptHandler, []},
      {"/priv/static/css/:css", ElixirCowboyExample.CssHandler, []},
      {"/priv/static/image/[...]", :cowboy_static, {:priv_dir, :elixir_cowboy_example, "static/image"}}
    ]
```

``` elixir:lib/elixir_cowboy_example/send_file_handler.ex
defmodule ElixirCowboyExample.SendFileHandler do
  def init(req, opts) do

    # fileを指定
    path = "priv/static/image/button.png"

    # fileサイズを取得
    %File.Stat{size: file_size} = File.stat!(path)

    header = %{"content-type" => "image/png"}

    # sendfileメソッドを使用してファイル送信するように指定を実施
    req = :cowboy_req.reply(200, header , 
            {:sendfile, 0, file_size, path}, req)

    {:ok, req, opts}
  end
end
```


# 記載したコードの実行
コードの記述が完了しましたので、それでは実行していきましょう。
いつも通り `iex -S mix` にて cowboy を実行していき、`http://localhost:4000/sendfile`にアクセスしてみましょう。
下記のように以前に作成したbutton.pngが表示されます


<img width="1176" alt="スクリーンショット 2017-01-15 15.10.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/3014/3946a24a-0b5f-689c-b5af-d8e8eae1aa4a.png">


# 最後に

今回はsendfileメソッドを使用してのファイルの送信を実施しました。
これは普通に送るのと、sendfileメソッドを使用して送る場合の違いなどはあるのか気になりますね。
それではまた次回

# 参考サイト
[Cowboy User Guide](https://ninenines.eu/docs/en/cowboy/1.0/guide/)
[Cowboy User Guide](https://ninenines.eu/docs/en/cowboy/2.0/guide/)