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

# はじめに
ElixirにてCowboyを直接動かすための記事となります。
[前回](http://qiita.com/hayabusa333/items/d049a6b6e3cca954ea39)の記事では、routeから画像ファイルなどのスタティックファイルを受け渡すための設定を行いました。
今回の記事では、ファイルのアップロードをおこなうための方法を記載していきます。

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

[Cowboy2.0のサンプルコードはこちらになります](https://github.com/hayabusa333/elixir_cowboy_example/tree/upload_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 |

# ファイルのアップロード機能を作成

今回はファイルのアップロード機能を作成していきます。
HTMLにてファイルの読み込みを実施し、Handlerにてリクエストに入っているバイナリ情報をFile.IOにて保存を実施していく内容となっています。

## cowboy 1.0の場合

``` html:priv/static/html/index.html
<html>
  <head>
    <meta charset=\"utf-8\">
      <title>Cowboy Hello!</title>
    <script type="text/javascript" src="priv/static/js/main.js"></script>
    <link rel="stylesheet" type="text/css" href="priv/static/css/main.css">
  </head>
  <body>
    <h1>Cowboy Hello!!</h1>
    <h2>file load test<h2>
    <img src="priv/static/image/button.png" class="button" type='submit' value='test' onclick="func()">
    <form method="post" enctype="multipart/form-data" action="/upload">
      <input type="file" name="inputfile"/>
      <input type="submit"/>
    </form>
  </body>
</html>
```

``` elixir:lib/elixir_cowboy_example.ex
    routes = [
      {"/", ElixirCowboyExample.Handler, []},
      # upload用のHandlerを追加
      {"/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/upload_handler.ex
defmodule ElixirCowboyExample.UploadHandler do
  def init({:tcp, :http}, req, opts) do
    {:ok, req, opts}
  end

  def handle(req, state) do
     # ファイル名を取得する
     {:ok, headers, req} = :cowboy_req.part(req)
     {:file, "inputfile", filename, content_type, _te} 
       = :cow_multipart.form_data(headers)
     # bodyからアップロードされたファイルのデータを取得
     {:ok, binary, req} = :cowboy_req.body(req)
     #取得した情報からファイルの保存を実施
     {:ok, file} = File.open("priv/static/upload/#{filename}", [:write])
     IO.binwrite(file, binary)
     File.close(file)

     # ファイルのアップロードを実施できたので、HTMLを返す
     head = [ {"content-type", "text/html"} ]
     body = "file upload ok"
     { :ok, reply } = :cowboy_req.reply(200, head, body, req)

     {:ok, req, state}
  end

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

```cmd
# upload用のファイルを配置するディレクトリを作成
$ mkdir priv/static/upload
```

## cowboy 2.0の場合

``` html:priv/static/html/index.html
<html>
  <head>
    <meta charset=\"utf-8\">
      <title>Cowboy Hello!</title>
    <script type="text/javascript" src="priv/static/js/main.js"></script>
    <link rel="stylesheet" type="text/css" href="priv/static/css/main.css">
  </head>
  <body>
    <h1>Cowboy Hello!!</h1>
    <h2>file load test<h2>
    <img src="priv/static/image/button.png" class="button" type='submit' value='test' onclick="func()">
    <form method="post" enctype="multipart/form-data" action="/upload">
      <input type="file" name="inputfile"/>
      <input type="submit"/>
    </form>
  </body>
</html>
```

``` elixir:lib/elixir_cowboy_example.ex
    routes = [
      {"/", ElixirCowboyExample.Handler, []},
      # upload用のHandlerを追加
      {"/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/upload_handler.ex
defmodule ElixirCowboyExample.UploadHandler do
  def init(req, opts) do
    # ファイル名を取得するための情報を取得
    {:ok, headers, req} = :cowboy_req.read_part(req)
    # bodyからアップロードされたファイルのデータを取得
    {:ok, binary, req} = :cowboy_req.read_part_body(req)
    # ファイル名を取得する
    {:file, "inputfile", filename, content_type, _te}
      = :cow_multipart.form_data(headers)
    # 取得した情報からファイルを保存する
    {:ok, file} = File.open("priv/static/upload/#{filename}", [:write])
    IO.binwrite(file, binary)
    File.close(file)

    #ファイルの保存ができたのでHTMLをレスポンスで返す
    head = %{"content-type" => "text/html"}
    body = "file upload ok"
    { :ok, reply } = :cowboy_req.reply(200, head, body, req)

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

```cmd
# upload用のファイルを配置するディレクトリを作成
$ mkdir priv/static/upload
```


# 記載したコードの実行
コードの記述が完了しましたので、それでは実行していきましょう。
いつも通り `iex -S mix` にて cowboy を実行していき、`http://localhost:4000/xxx`にアクセスしてみましょう。
下記のようにブラウザの画面に表示され、ファイル送信ボタンからファイルを選択し、送信ボタンを押下して、設定した`priv/static/upload`ディレクトリにファイルが保存されていれば成功です。

<img width="1176" alt="スクリーンショット 2017-01-12 12.44.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/3014/b2718f7e-56e2-f0b2-d4ea-aa8d3e796949.png">

<img width="1176" alt="スクリーンショット 2017-01-12 12.44.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/3014/50a0e719-c52c-ec7f-dd43-2f7aaaeb24ad.png">


# 最後に
今回はファイルのuploadを実装しました。
エラー処理などは実施しておりませんので、エラーが発生した場合などの実装が別途必要になりますので注意が必要です。
それではまた次回

# 参考サイト
[Cowboy User Guide](https://ninenines.eu/docs/en/cowboy/1.0/guide/)
[Cowboy User Guide](https://ninenines.eu/docs/en/cowboy/2.0/guide/)
[Multipart upload example](https://github.com/ninenines/cowboy/tree/master/examples/upload)
[elixir + cowboyでwebアプリ　その６　画像のアップロードとpostの最大値変更](http://symfoware.blog68.fc2.com/blog-entry-1775.html)