上传文件
import web
urls = (
'/upload', 'Upload',
)
class Upload:
def GET(self):
return """<html><head></head><body>
<form method="POST" enctype="multipart/form-data" action="">
<input type="file" name="myfile" />
<br/>
<input type="submit" />
</form>
</body></html>"""
def POST(self):
x = web.input(myfile={})
web.debug(x['myfile'].filename) # 这里是文件名
web.debug(x['myfile'].value) # 这里是文件内容
web.debug(x['myfile'].file.read()) # 或者使用一个文件对象
print x
raise web.seeother('/upload')
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
如果是get请求,则返回一个表单,给用户选择文件来上传,input类型是"file". 注意要加上enctype="multipart/form-data", 否则不能正常工作。 如果是post请求,首先获取上传文件x = web.input(myfile={})
.
这里的参数myfile={}容易让人迷惑,我们首先不带这个参数做一个尝试:x = web.input(). 得到的x是一个Storage对象如<Storage {'myfile': 'file-content'}>. 这里的Storage对象与字典基本一样,只是可以通过属性直接访问关键字的值,如x.myfile可以直接得到文件内容。
为了理解myfile={}参数,需要看一下web.input()函数的源码:
def input(*requireds, **defaults):
"""
Returns a `storage` object with the GET and POST arguments.
See `storify` for how `requireds` and `defaults` work.
"""
_method = defaults.pop('_method', 'both')
out = rawinput(_method)
try:
defaults.setdefault('_unicode', True) # force unicode conversion by default.
return storify(out, *requireds, **defaults)
except KeyError:
raise badrequest()
可以知道函数返回一个Storage对象,其中主要调用storify(out, *requireds, **defaults)
函数来 得到这个对象。
storify(mapping, *requireds, **defaults): 函数通过mapping规则来返回一个Storage字典,如果关键字 不存在就查看参数defaults.
storify({'a':1, 'c':3}, b=2, c=0) -> storage({'a':1, 'b':2, 'c':3})
但是如果mapping里关键字对应的值是一个list,则会默认取出list中最后一个因素的值最为storage中关键字的值, 除非在default参数中指定关键字的对应值是一个list,如
storify({'a': [1, 2]}) -> storage({'a': 2})
storify({'a': [1, 2]}, a=[]).a -> [1, 2]
storify({'a': 1}, a=[]).a -> [1]
类似的,如果关键字对应的值有'value'的属性,比如关键字对应的值是一个storage对象,则 函数也会取出'value'对应的值,除非关键字在defaults中以字典形式存在才会保留整个storage对象,如
storify({'a':storage(value=1)}).a -> 1
storify({'a':storage(value=1)}, a={}).a -> <Storage {'value': 1}>
现在就可以理解x = web.input(myfile={})参数了,作用是让返回的对象保持字典的形式,得到的x是 <Storage {'myfile': FieldStorage('myfile', 'filename', 'file-content')}>. 因此 x.myfile就可以直接得到我们的FieldStorage
对象。FieldStorage对象提供了文件存储的一些操作, 有几个属性:name, filename, value, file, type, headers, ... 其中file对象是文件对象,可以通过x['myfile'].file.read()来读取。
保存上传的文件
class Upload:
def GET(self):
class Upload:
def GET(self):
...
def POST(self):
x = web.input(myfile={})
filedir = 'path/where/you/want/to/save'
if 'myfile' in x:
# 将windows路径转为linux路径
filepath = x.myfile.filename.replace('\\', '/')
filename = filepath.split('/')[-1] # the filename with extension
fout = open(filedir + '/' + filename, 'w')
fout.write(x.myfile.file.read())
fout.close()
raise web.seeother('/upload')