はじめに
ElixirにてCowboyを直接動かすための記事となります。
前回の記事では、routeから画像ファイルなどのスタティックファイルを受け渡すための設定を行いました。
今回の記事では、ファイルのアップロードをおこなうための方法を記載していきます。
バージョン
使用した言語やライブラリのバージョンは下記となります。
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>
<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>
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"}}
]
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の場合
<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>
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"}}
]
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
ディレクトリにファイルが保存されていれば成功です。
最後に
今回はファイルのuploadを実装しました。
エラー処理などは実施しておりませんので、エラーが発生した場合などの実装が別途必要になりますので注意が必要です。
それではまた次回
参考サイト
Cowboy User Guide
Cowboy User Guide
Multipart upload example
elixir + cowboyでwebアプリ その6 画像のアップロードとpostの最大値変更