图片上传和展示
图片上传
上传表单和文件保存
-
self.request.files 的使用
-
Python 操作文件,写入数据
获取一个表单上传的文件列表 可以使用
self.request.files.get('newimg')
,参数填写 HTML 中的
<input type="file" name='newimg'>
每个文件都是一个字典的形式
{"filename":..., "content_type":..., "body":...}
.form表单
enctype="multipart/form-data"
; 如果没用这种格式, 原生上传的数据可以调用self.request.body
使用. 默认上传的文件是完全缓存在内存中的;
code
main.py
class UploadHandler(tornado.web.RequestHandler):
"""
接受图片上传
"""
def get(self, *args, **kwargs):
self.render('upload.html')
def post(self, *args, **kwargs):
# 提取表单中‘name’为‘newimg’的文件元数据 获取上传文件信息
img_files = self.request.files.get('newimg') #
print(img_files) #[{"filename": ..., "content_type": ..., "body": ...},]
for img_file in img_files:
# img_file['filename']获取文件的名称 有些文件需要以二进制的形式存储
with open('./static/uploads/' + img_file['filename'], 'wb') as f:
f.write(img_file['body']) # img_file['body']获取文件的内容
self.write({'msg':'got file: {}'.format(img_files[0]['filename'])})
ssh://pyvip@127.0.0.1:1234/home/pyvip/.virtualenvs/py3env/bin/python3 -u /home/pyvip/py_case/tornado2项目/app.py
upload.html
{% extends 'base.html' %}
{% block title %}
list post page
{% end %}
{% block content %}
{#entype 设置编码格式 上传文件:multipart/form-data#}
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="file" name="newimg">
<input type="submit">
</form>
{% end %}
图片展示
用简单的目录检索来展示
使用 Python 标准库 glob
code
main.py
class IndexHandler(tornado.web.RequestHandler):
"""
首页
"""
def get(self, *args, **kwargs):
# 获取该路径下所有的大图的路径
imgs = photo.get_images('uploads')
self.render('index.html', imgs=imgs)
index.html
{% extends 'base.html' %}
{% block title %}
index page
{% end %}
{% block content %}
{% for i in imgs %}
<img src="{{ static_url(i) }}" width="666px">
{% end %}
{% end %}
photo.py
import glob
import os
def get_images(path):
"""
获取static目录下 path目录里所有 .jpg 结尾的 文件
:param path: uploads
:return:
"""
os.chdir('static')
imgs = glob.glob('{}/*.jpg'.format(path))
os.chdir('..')
return imgs
def get_images2(path):
"""
获取static目录下 path目录里所有 .jpg 结尾的 文件
:param path: static/uploads
:return:
"""
images = []
for file in glob.glob(path + '/*.jpg'):
images.append(file)
return images
def get_images3(path):
"""
获取static目录下 path目录里所有 .jpg 结尾的 文件
:param path: static/uploads
:return:
"""
imgs = glob.glob('{}/*.jpg'.format(path))
return imgs
缩略图生成
pip install pillow
使用 PIL
from PIL import Image
import glob, os
imgs = glob.glob('*.jpg')
for img in imgs:
#os.path.splitext()将文件名和扩展名分开
file, ext = os.path.splitext(img)
im = Image.open(img) # 打开一个jpg图像文件,注意是当前路径
im.thumbnail((200, 200)) # 长200 宽200 的缩放
# 保存
im.save("{}_{}x{}.jpg".format(file, 200, 200), "JPEG")
glob.glob() 返回所有匹配的文件路径列表
os.path.basename()
返回path最后的文件名。如果path以/或\结尾,那么就会返回空值。
s = '/static/uploads/1202983.jpg'
>>> os.path.basename(s)
'1202983.jpg'
main.py
class ExploreHandler(tornado.web.RequestHandler):
"""
发现页
"""
def get(self, *args, **kwargs):
# 获取该路径下所有的大图的路径
# ['./static/uploads/thumbs/1106620_200x200.jpg', './static/uploads/thumbs/1106622_200x200.jpg',...]
imgs = photo.get_images('uploads/thumbs')
self.render('explore.html', imgs=imgs)
class UploadHandler(tornado.web.RequestHandler):
"""
接受图片上传
"""
def get(self, *args, **kwargs):
self.render('upload.html')
def post(self, *args, **kwargs):
# 提取表单中‘name’为‘newimg’的文件元数据 获取上传文件信息
img_files = self.request.files.get('newimg', None)
print(img_files) # [{"filename": ..., "content_type": ..., "body": ...},]
print(img_files[0]['filename']) # 例:1178645.jpg
file_size = self.request.headers.get('Content-Length') # 18539
print(file_size)
if img_files:
for img_file in img_files:
# img_file['filename']获取文件的名称 有些文件需要以二进制的形式存储
save_to = './static/uploads/{}'.format(img['filename'])
with open(save_to, 'wb') as f:
f.write(img_file['body']) # img_file['body']获取文件的内容
# 生成缩略图
photo.make_thumb(save_to)
self.write({'msg': 'got file: {}'.format(img_files[0]['filename'])})
else:
self.write({'msg': 'empty form data'})
explore.html
{% extends 'base.html' %}
{% block title %}
explore page
{% end %}
{% block content %}
{% for i in imgs %}
<img src="{{ static_url(i) }}" width="200px">
{% end %}
{% end %}
photo.py
import glob
import os
from PIL import Image
def make_thumb(path):
"""
为指定的path文件生成它所在目录的 thumbs 目录下的小图文件
:param path: ./static/uploads/701728.jpg
:return:
"""
im = Image.open(path)
size = (200, 200)
im.thumbnail(size)
basename = os.path.basename(path) # 701728.jpg
dirname = os.path.dirname(path) # ./static/uploads
file, ext = os.path.splitext(basename)
# ./ static / uploads / thumbs / 701728_200x200 .jpg
save_thumb_to = os.path.join(dirname, 'thumbs', '{}_{}x{}{}'.format(file, *size, ext))
im.save(save_thumb_to, "JPEG")
作业
图片上传后生成缩略图,并展示在 explore 页面(提交简单的代码就可以了,主要是自己动手尝试)
with open
app.py 与 static 同级 两种效果一样
with open("static/uploads/1.jpg","wb") as file:
with open("./static/uploads/1.jpg","wb") as file:
代码:
app.py
import os
import tornado.ioloop
import tornado.options
import tornado.web
from tornado.options import define, options
from handlers import main
define('port', default='8000', type=int, help='Listening port')
class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r'/', main.IndexHandler),
(r'/explore', main.ExploreHandler),
(r'/post/(?P<post_id>[0-9]+)', main.PostHandler),
(r'/upload', main.UploadHandler),
]
settings = dict(
debug=True,
template_path='template',
static_path='static', # 相对路径
# static_path=os.path.join(os.path.dirname(__file__), 'static'), # 绝对路径
)
super(Application, self).__init__(handlers, **settings)
application = Application()
if __name__ == '__main__':
tornado.options.parse_command_line()
application.listen(options.port)
print("Server start on port {}".format(str(options.port)))
tornado.ioloop.IOLoop.current().start()
main.py
import tornado.web
from utils import photo
import os
class IndexHandler(tornado.web.RequestHandler):
"""
首页
"""
def get(self, *args, **kwargs):
# 获取该路径下所有的大图的路径
imgs = photo.get_images('uploads')
self.render('index.html', imgs=imgs)
class ExploreHandler(tornado.web.RequestHandler):
"""
发现页
"""
def get(self, *args, **kwargs):
# 获取该路径下所有的大图的路径
imgs = photo.get_images('uploads/thumbs')
self.render('explore.html', imgs=imgs)
class PostHandler(tornado.web.RequestHandler):
"""
详情页
"""
def get(self, post_id):
self.render('post.html', post_id=post_id)
class UploadHandler(tornado.web.RequestHandler):
"""
接受图片上传
"""
def get(self, *args, **kwargs):
self.render('upload.html')
def post(self, *args, **kwargs):
# 提取表单中‘name’为‘newimg’的文件元数据 获取上传文件信息
img_files = self.request.files.get('newimg')
print(img_files) # [{"filename": ..., "content_type": ..., "body": ...},]
print(img_files[0]['filename']) # 例:1178645.jpg
file_size = self.request.headers.get('Content-Length') # 18539
print(file_size)
if img_files:
for img in img_files:
# img_file['filename']获取文件的名称 有些文件需要以二进制的形式存储
save_to = './static/uploads/{}'.format(img['filename'])
with open(save_to, 'wb') as f:
f.write(img['body']) # img_file['body']获取文件的内容
# 生成缩略图
photo.make_thumbs(save_to)
self.write({'msg': 'got file: {}'.format(img_files[0]['filename'])})
else:
self.write({'msg': 'empty form data'})
photo.py
import os
import glob
from PIL import Image
def get_images(path):
"""
获取static目录下 path目录里所有 .jpg 结尾的 文件
:param path: uploads
:return:
"""
os.chdir('static')
images = glob.glob('{}/*.jpg'.format(path))
os.chdir('..')
return images
def make_thumbs(path):
"""
为指定的path文件生成它所在目录的 thumbs 目录下的小图文件
:param path: ./static/uploads/701728.jpg
:return:
"""
# ./ static / uploads / 701728.jpg
im = Image.open(path)
size = (200, 200)
im.thumbnail(size)
# ./ static / uploads /thumbs/ 701728_200x200.jpg
dirname = os.path.dirname(path) # ./ static / uploads
basename = os.path.basename(path) # 701728.jpg
file, ext = os.path.splitext(basename)
save_thumbs_to = os.path.join(dirname, 'thumbs', '{}_{}x{}{}'.format(file, *size, ext))
im.save(save_thumbs_to, "JPEG")
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}Title{% end %}</title>
</head>
<body>
<div style="width: 800px; text-align: center">
{% block content %}
base content
{% end %}
</div>
</body>
</html>
index.html
{% extends 'base.html' %}
{% block title %}
index page
{% end %}
{% block content %}
{% for i in imgs %}
<img src="{{ static_url(i) }}" width="666px">
{% end %}
{% end %}
explore.html
{% extends 'base.html' %}
{% block title %}
explore page
{% end %}
{% block content %}
{% for i in imgs %}
<img src="{{ static_url(i) }}" width="200px">
{% end %}
{% end %}
post.html
{% extends 'base.html' %}
{% block title %}
post page
{% end %}
{% block content %}
<img src="{{ static_url("images/{}.jpg".format(post_id)) }} " width=666">
{% end %}
upload.html
{% extends 'base.html' %}
{% block title %}
list post page
{% end %}
{% block content %}
{#entype 设置编码格式 上传文件:multipart/form-data#}
<form action="/upload" enctype="multipart/form-data" method="post">
<input type="file" name="newimg">
<input type="submit">
</form>
{% end %}