HTMLでアップロードされたファイルを保存するCGIスクリプトを作成するにはどうすればいいでしょうか
解決済
回答 1
投稿
- 評価 2
- クリップ 2
- VIEW 9,598
以下のサイトを参考に、HTMLからアップロードされたfileを受け取り保存するCGIスクリプトをpythonで作成したいと考えております。
http://www.gesource.jp/programming/python/cgi/0115.html
しかしながらいざ実行してみると、HTMLはちゃんと作成できファイル送信フォームも生成できたのですが、送信すると以下のエラーが出てしまいます。
Error response
Error code: 501
Message: Can only POST to CGI scripts.
Error code explanation: 501 - Server does not support this operation.
test15.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html" charset="UTF-8" />
<title>ファイルをアップロードする</title>
</head>
<body>
<h1>ファイルをアップロードする</h1>
<p>%s</p>
<form action="test15.cgi" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" />
</form>
</body>
</html>
test15.cgi
import cgi
import os, sys
try:
import msvcrt
msvcrt.setmode(0, os.O_BINARY)
msvcrt.setmode(1, os.O_BINARY)
except ImportError:
pass
result = ''
form = cgi.FieldStorage()
if form.has_key('file'):
item = form['file']
if item.file:
fout = file(os.path.join('/tmp', item.filename), 'wb')
while True:
chunk = item.file.read(1000000)
if not chunk:
break
fout.write(chunk)
fout.close()
result = 'アップロードしました。'
print html % result
print("upload is done")
当方、CGIについて最近勉強したばかりで筋違いな質問であれば大変申し訳ないです。
HTMLで送信したファイルがtmpフォルダに保存されるようなCGIを作りたいと考えております。
何卒、よろしくお願いいたします。
-
クリップを取り消します
-
質問の評価を上げたことを取り消します
-
質問の評価を下げたことを取り消します
checkベストアンサー
+3
こんにちは。
サーバーがステータス501を返しているので、cgiスクリプトが正しく動作して
いないようです。ご提示のコードですと、何点か問題ありそうでした。
- 1行目でシバン(Shebang)にてスクリプトが指定されていないので、
pythonスクリプトとして動作できない。 - 日本語部分があるので、文字コードを指定しないと文字化けの恐れがある。
- HTTPレスポンスとして返す時のContent-Type が指定されていない。
- 'html' 変数に初期値が設定(宣言)されていない。未定義変数エラー。
プログラムを造ってサーバーに設置したときは、cgiとしてサーバーに
実行させる前に端末上で文法チェックしてみると良いです。
以下で簡単に文法チェックすることができます。
(もちろん、実行時のエラーはこれでは分かりません)
$ python -m py_compile test15.cgi
ご提示のコードですが、以下のように直すことで動作しました。
確認用のコードを残していますので、差分を取って比較してみてください。
尚、文字コードはutf-8で保存してください。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cgi
import os, sys
try:
import msvcrt
msvcrt.setmode(0, os.O_BINARY)
msvcrt.setmode(1, os.O_BINARY)
except ImportError:
pass
result = 'DUMMY'
form = cgi.FieldStorage()
if form.has_key('file'):
item = form['file']
if item.file:
fout = file(os.path.join('/tmp', item.filename), 'wb')
while True:
chunk = item.file.read(1000000)
if not chunk:
break
fout.write(chunk)
fout.close()
#result = 'upload is done'
result = 'アップロード'
#print html % result
print "Content-Type: text/html"
print
html = "<html><body>%s</body><html>"
print html % result
python3に関して追記
python3 でのご質問だったのかもしれませんので、すみませんが以下、追記させていただきます。
参考にされたサイト様のサンプルプロはpython2 のものです。
私が提示したコードもpython2 のものなので、サーバー上でpython3でcgiを
稼動させる場合、文法エラーで動作しません。
コードをpython3でほぼ等価なものに書き直し、動作確認したものを以下に示します。
※「アップロード」の部分はそのままだとエラーになり、
コードが煩雑になるのでASCII文字列に直させてもらいました。
今後pythonでcgiを造られる場合は、バージョンの違いに注意する必要があるかとは思います。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import cgi
import os, sys
try:
import msvcrt
msvcrt.setmode(0, os.O_BINARY)
msvcrt.setmode(1, os.O_BINARY)
except ImportError:
pass
result = 'DUMMY'
form = cgi.FieldStorage()
#if form.has_key('file'):
if 'file' in form:
item = form['file']
if item.file:
# fout = file(os.path.join('/tmp', item.filename), 'wb')
fout = open(os.path.join('/tmp', item.filename), 'wb')
while True:
chunk = item.file.read(1000000)
if not chunk:
break
fout.write(chunk)
fout.close()
result = 'upload is done'
#result = "アップロード"
print("Content-Type: text/html")
print("")
html = "<html><body>{0}</body><html>"
print(html.format(result))
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 87.60%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
dodox86
2017/10/01 18:26
print("STEP#1: ", file=sys.stderr)
と記述すると、アクセスログには
127.0.0.1 - - [01/Oct/2017 18:16:53] "POST /cgi-bin/test17.cgi HTTP/1.1" 200 -
STEP#1:
のように出ますので、デバッガーを用意するのが大変な場合は代替策のひとつになります。また、Windows環境では '/tmp'の代わりに TEMP環境変数で出力されるディレクトリが書き込み可能です。
書き込み可能なディレクトリを新設するのが難しい場合、コンソール(コマンドプロンプト)上で
C> echo %TEMP%
で表示されたディレクトリを'/tmp'の代わりに利用することもできます。ご参考まで。
dodox86
2017/10/01 18:31
mmss
2017/10/01 18:39
書き込み可能、のところも少々疑心暗鬼でしたので、ぜひご教授いただいたアドバイスを利用させていただきます!!何から何までご助力いただき、誠にありがとうございました。