LoginSignup
1
1

More than 5 years have passed since last update.

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

Posted at

はじめに

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

Cowboy1.0のサンプルコードはこちらになります

Cowboy2.0のサンプルコードはこちらになります

バージョン

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

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の場合

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>
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"}}
    ]
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
# upload用のファイルを配置するディレクトリを作成
$ mkdir priv/static/upload

cowboy 2.0の場合

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>
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"}}
    ]
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
# upload用のファイルを配置するディレクトリを作成
$ mkdir priv/static/upload

記載したコードの実行

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

スクリーンショット 2017-01-12 12.44.52.png

スクリーンショット 2017-01-12 12.44.29.png

最後に

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

参考サイト

Cowboy User Guide
Cowboy User Guide
Multipart upload example
elixir + cowboyでwebアプリ その6 画像のアップロードとpostの最大値変更

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1