![]() |
ノート/PythonをCGIプログラムとして使うhttp://pepper.is.sci.toho-u.ac.jp/pepper/index.php?%A5%CE%A1%BC%A5%C8%2FPython%A4%F2CGI%A5%D7%A5%ED%A5%B0%A5%E9%A5%E0%A4%C8%A4%B7%A4%C6%BB%C8%A4%A6 |
![]() |
ノート
訪問者数 6746 最終更新 2015-05-21 (木) 16:07:16
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import codecs import cgitb cgitb.enable() sys.stdout = codecs.getwriter('utf_8')(sys.stdout) print ('Content-type: text/html; charset=UTF-8') print("\r\n\r\n") print(u"あいう")
ポイントは、
このファイルを、cgi-binディレクトリ下に置けば、呼び出せる。
例 (ここでは、formを書き出すhtml部分も同じプログラム中でprintで出力している)
#!/usr/bin/env python # -*- coding: utf-8 -*- # coding: utf-8 import sys import codecs import cgi import cgitb cgitb.enable() sys.stdout = codecs.getwriter('utf_8')(sys.stdout) print ('Content-type: text/html; charset=UTF-8') print ("\r\n\r\n") form = cgi.FieldStorage() laptops = form.getvalue('laptops','0') desktops = form.getvalue('desktops','0') print """ <html> <body> <form action='mytest.py'> How many laptops do you own <input type='radio' checked name='laptops' value='0' />0 <input type='radio' name='laptops' value='1' />1 <input type='radio' name='laptops' value='2' />2 <p> How many desktops do you own <input type='radio' checked name='desktops' value='0' />0 <input type='radio' name='desktops' value='1' />1 <input type='radio' name='desktops' value='2' />2 <p> <input type='submit' value='送る' /> <p> You own %d computers. </form> </body> </html>""" % (int(laptops)+int(desktops))
この例では、次のようなことに注目する。
例
#!/usr/local/bin/python # -*- coding: utf-8 -*- import sys,os,codecs import cgi import cgitb cgitb.enable() sys.stdout = codecs.getwriter('utf_8')(sys.stdout) print ('Content-type: text/html; charset=UTF-8') print ("\r\n\r\n") html = u''' <html> <head> <meta http-equiv="Content-Type" content="text/html" charset="UTF-8" /> <title>ファイルアップロード</title> </head> <body> <form action="upload.py" method="post" enctype="multipart/form-data"> <input type="file" name="file" multiple/> <input type="submit" /> </form> </body> </html> ''' result = '' form = cgi.FieldStorage() if form.has_key("file"): fileitem = form['file'] if (isinstance(fileitem, list)): # Multi-File for i in range(0, len(fileitem)): fout = file(os.path.join('/tmp', fileitem[i].filename), 'wb') while True: chunk = fileitem[i].file.read(1000000) if not chunk: break fout.write(chunk) fout.close() else: # Single-File fout = file(os.path.join('/tmp', fileitem.filename), 'wb') while True: chunk = fileitem.file.read(1000000) if not chunk: break fout.write(chunk) fout.close() print html + result
ポイントは、 fileitem = form['file'] で返ってくる値が、複数ファイルの時はリストになって、複数のファイルを扱える。
この fileitem が、ファイルを1つだけしかアップロードしない時(リストにならない)と、複数ファイルをアップロードした時(リストになる)で、形が違う。
従って、取り出す時に区別する必要がある。
複数ファイルの時は、 fileitem[i] のように、どのファイルかを区別する。また、len(filename)によって、ファイルの個数を知ることができる。単一ファイルの時にlen(filename)を行うと(単一オブジェクトのlenを取ることになるので)エラーになる。
fileitemの属性は、元のファイルの名前が filename、ファイルの内容が valueである。
SELinux下では、httpdによる書き込みは一般には止められる。(Permission Denied) 特定のディレクトリに対して書き込みを許可するには、
%semanage fcontext -a -t httpd_sys_content_rw_t "/var/www/html/fcs20/FILE" %semanage fcontext -a -t httpd_sys_content_rw_t "/var/www/html/fcs20/FILE/*" %restorecon -R -v /var/www/html/fcs20/FILE restorecon reset /var/www/html/fcs20/FILE context system_u:object_r:httpd_sys_content_t:s0->system_u:object_r:httpd_sys_content_rw_t:s0
この辺も参照
#!/usr/bin/env python # -*- coding: utf-8 -*- # coding: utf-8 import sys import codecs import cgi import cgitb cgitb.enable() sys.stdout = codecs.getwriter('utf_8')(sys.stdout) print ('Content-type: text/html; charset=UTF-8') print ("\r\n\r\n") form = cgi.FieldStorage() print("タイプは" + str(form.type) + "<br>") if (form.type != "application/x-www-form-urlencoded"): fileitem = form['userfile[]'] if (isinstance(fileitem, list)): # Multiple files print(" 複数ファイルです<br>") print(" ファイル数は" + str(len(fileitem)) + "<br>") for i in range(0, len(fileitem)): print(str(fileitem[i].filename) + "<br>") fp = open("/var/www/html/fcs20/FILE/"+str(fileitem[i].filename), "w+") fp.write(fileitem[i].value) else: print (" 単数ファイルです<br>") print(str(fileitem.filename) + "<br>") fp = open("/var/www/html/fcs20/FILE/"+str(fileitem.filename), "w+") fp.write(fileitem.value) print""" <html> <body> <form action="multifile2.py" method="post" enctype="multipart/form-data"> Send these files:<br /> <input type="hidden" name="MAX_FILE_SIZE" value="300000" /> <input name="userfile[]" type="file" multiple/><br /> <input type="submit" value="Send files" /> </form> </body> </html> """
気をつけるのは、同じnameの下に複数の値が返される時、リストで返されるが、単一の時はリストでないので、その区別をすること。⇒ 参考 マニュアル
#!/usr/bin/env python # -*- coding: utf-8 -*- # coding: utf-8 import sys import codecs import os import cgi import cgitb cgitb.enable() sys.stdout = codecs.getwriter('utf_8')(sys.stdout) print ('Content-type: text/html; charset=UTF-8') print ("\r\n\r\n") datadir = "/var/www/html/fcs20/FILE/" form = cgi.FieldStorage() print("nameは" + str(form.name) + "<br>") print("valueは" + str(form.getvalue("submit")) + "<br>") print("タイプは" + str(form.type) + "<br>") if (form.getvalue("submit") == "消去"): print(str(form) + "<br>") if ("fnum" in form) : selectitem = form['fnum'] print(str(selectitem) + "<br>") if (isinstance(selectitem,list)) : for i in range(0, len(selectitem)): print(str(selectitem[i].value)) else: print(str(selectitem.value)) else: print('no checks') else: if (form.type == "multipart/form-data"): fileitem = form['userfile[]'] if (isinstance(fileitem, list)): # Multiple files print(" 複数ファイルです<br>") print(" ファイル数は" + str(len(fileitem)) + "<br>") for i in range(0, len(fileitem)): print(str(fileitem[i].filename) + "<br>") #print(fileitem[i].value) #print("<br>=======================<br>") fp = open(datadir+str(fileitem[i].filename), "w+") # fp = open("/tmp/"+str(fileitem[i].filename), "r+") fp.write(fileitem[i].value) else: print (" 単数ファイルです<br>") print(str(fileitem.filename) + "<br>") #print(fileitem.value) fp = open(datadir+str(fileitem.filename), "w+") # fp = open("/tmp/"+str(fileitem.filename), "r+") fp.write(fileitem.value) print""" <html> <head> <META http-equiv="Content-Type" content="text/html;charset=utf-8"> <title> FCS20 </title> </head> <body> <table> <tr><td width=300> """ i = 0 print("作業フォルダ内のファイル一覧<br>") print('<form action="fcs20.py" method="post" enctype="multipart/form-data">') print("<table><tr><td>") for f in (os.listdir(datadir)): print('<input type="checkbox" name=fnum value=' + str(i) +"> " + str(f) + "</td></tr><tr><td>") i=i+1 print("</tr></td></table>") print('<input type="submit" name="submit" value="消去" />') print("</form>") print""" </td><td> 追加ファイルの転送<br> <form action="fcs20.py" method="post" enctype="multipart/form-data"> <input type="hidden" name="MAX_FILE_SIZE" value="30000000" /> <input width=300 name="userfile[]" type="file" multiple/><br /> <input type="submit" name="submit" value="転送" /> </form> </td></tr></table> </body> </html> """
なお、SELinuxのいろいろな許可ビットの一覧を見るには、