nginx 1.6.2 + lua-nginx-moduleで簡易ファイルアップローダー
nginxの組み込みLuaが動く環境を作ってみました。Debian 7 + nginx 1.6.2 + lua-nginx-moduleの環境構築
具体的な使い方を調べてみます。
最終的には、postされたファイルを保存するLuaプログラムを作ってみます。
post値の受け取り
http://wiki.nginx.org/HttpLuaModule
こちらを参考にLuaでpost値を受け取る方法を調べてみました。
nginx.confはこんな感じ。
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
content_by_lua_file /opt/nginx/lua/sample.lua;
}
}
}
/opt/nginx/lua/sample.luaはこんなかんじです。
以降、このファイルを編集して動作を試してみます。
- -- リクエストの内容を解析
- ngx.req.read_body()
- -- post値を取得
- local args, err = ngx.req.get_post_args()
- if not args then
- ngx.say("failed to get post args: ", err)
- return
- end
- -- key:valueの形式で応答
- for key, val in pairs(args) do
- ngx.say(key, ": ", val)
- end
テスト用のプログラムはPythonで記載しました。
- # -*- coding:utf-8 -*-
- import urllib
- import urllib2
- url = "http://192.168.1.102/"
- params = urllib.urlencode({'name':1, 'item_id':2})
- req = urllib2.Request(url, params)
- res = urllib2.urlopen(req)
- print res.read()
動かしてみると、こんな応答があります。
Luaプログラムが動いてくれているようです。
$ python post.py
item_id: 2
name: 1
最初、画像データをbase64エンコードしてpostすればいいと
思っていたのですが、ちょっと大きめの画像だと
あっさり500エラーになり頓挫しました。
別の作戦を考えてみます。
画像データのpost
nginx-lua and nginx upload module
こちらのサンプルが参考になりそうです。
かなりハマったのですが、やっていて理解したことは
・そんなに大きくないデータ(75KB未満?)だと、ngx.req.get_body_data()で
postされたデータが取得できる。
・それなりの大きさだと、nginxが自動的にテンポラリファイルに保存する。
テンポラリファイルの名前はngx.req.get_body_file()で取得できる
上記のことを踏まえて、こんなluaプログラムを書いてみます。
- -- bodyの解析
- ngx.req.read_body()
- -- body_dataを取得してみる
- local req_body = ngx.req.get_body_data()
- -- もし取得できていなかったら、データはファイルに行っている
- if not req_body then
- -- テンポラリのファイル名を取得。内容を全部読み込む
- local req_body_file_name = ngx.req.get_body_file()
- local file = io.open(req_body_file_name, 'rb')
- req_body = file:read('*a')
- file:close()
- end
- -- ファイル保存
- f = io.open("/tmp/test.png", "wb")
- f:write(req_body)
- f:close()
- ngx.say('ok')
データを送ってみるPythonプログラムはこちら。
- # -*- coding:utf-8 -*-
- import urllib
- import urllib2
- import base64
- url = "http://192.168.1.102/"
- with open('sample.png', 'rb') as f:
- image = f.read()
- req = urllib2.Request(url, data=image)
- res = urllib2.urlopen(req)
- print res.read()
出来ました。
HTTP Error 413: Request Entity Too Large
はしゃいで15MBぐらいの画像アップロードを試してみると、
urllib2.HTTPError: HTTP Error 413: Request Entity Too Large
というエラーが発生します。
Nginx での 413 Request Entity Too Large エラーの対処法
こちらを参考にnginx.confを編集。
client_max_body_size 20M;の記載を追加します。
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
client_max_body_size 20M;
server {
listen 80;
server_name localhost;
location / {
content_by_lua_file /opt/nginx/lua/sample.lua;
}
}
}
これでアップロードできるようになりました。
ファイルの保存先
バイナリでデータが送信できるようになったので、msgpackを使って
保存先のファイルパスと実データを送信ということもできそうです。
今回は、リクエストヘッダー情報にファイル名を含めることにしました。
リクエストヘッダーの情報は
ngx.req.get_headers()
で取得できます。
luaのプログラム
- -- bodyの解析
- ngx.req.read_body()
- -- body_dataを取得してみる
- local req_body = ngx.req.get_body_data()
- -- もし取得できていなかったら、データはファイルに行っている
- if not req_body then
- -- テンポラリのファイル名を取得。内容を全部読み込む
- local req_body_file_name = ngx.req.get_body_file()
- local file = io.open(req_body_file_name, 'rb')
- req_body = file:read('*a')
- file:close()
- end
- -- ヘッダーから保存するときのファイル名を取得
- filename = ngx.req.get_headers()["filename"]
- -- ファイル保存
- f = io.open("/tmp/" .. filename, "wb")
- f:write(req_body)
- f:close()
- ngx.say(filename)
- ngx.say('ok')
テスト用のPythonプログラム
- # -*- coding:utf-8 -*-
- import urllib
- import urllib2
- import base64
- url = "http://192.168.1.102/"
- with open('sample.png', 'rb') as f:
- image = f.read()
- req = urllib2.Request(url, data=image)
- req.add_header('filename', 'upload.png')
- res = urllib2.urlopen(req)
- print res.read()
これで狙い通りの動きになりました。
【参考URL】
http://wiki.nginx.org/HttpLuaModule
nginx-lua and nginx upload module
Nginx での 413 Request Entity Too Large エラーの対処法
Luaのお勉強 文字列の連結やtableの使い方
PythonからREST API経由でRedmineにチケットを登録する(XML,JSON使用)
- 関連記事
-
- luviでLuaプログラムをバイナリの実行形式に変換する
- nginx 1.6.2 + lua-nginx-moduleでapache2 mod_access_tokenを実装
- nginx 1.6.2 + lua-nginx-moduleで簡易ファイルアップローダー
- Debian 7 + nginx 1.6.2 + lua-nginx-moduleの環境構築
- Luaでメールの送信を行う
コメント