本文将介绍笔者的一个项目,主要是利用tornado实现表格文件的预览,能够浏览的表格文件支持CSV以及Excel文件。预览的界面如下:

文件浏览界面

  下面我们将看到这个功能是如何通过tornado来实现的。

  该项目的代码结构如下图所示:

项目的代码结构

  其中主要分为四个部分:

  • files
  • static
  • templates
  • py代码

其中,files文件夹为上传的表格文件的存放路径,static为前端的静态文件,后续将不用给出介绍,读者可以从该项目的github中下载(下载地址详见后面),templates文件夹主要存放HTML文件,而py文件用于后端控制。

  首先让我们看三个HTML文件,先是upload.html,其代码如下:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>文件上传</title>
  6. <link rel="shortcut icon" href="{{static_url('images/flower.ico')}}">
  7. <link rel="stylesheet" href="{{static_url('CSS/amazeui.min.css')}}">
  8. <script src="{{static_url('JS/amazeui.min.js')}}"></script>
  9. <script>
  10. $(function() {
  11. $('#doc-form-file').on('change', function() {
  12. var fileNames = '';
  13. $.each(this.files, function() {
  14. fileNames += '<span class="am-badge">' + this.name + '</span> ';
  15. });
  16. $('#file-list').html(fileNames);
  17. });
  18. });
  19. </script>
  20. </head>
  21. <body>
  22. <div align="center">
  23. <br><br>
  24. <h1>表格文件上传</h1>
  25. <form action='file' enctype="multipart/form-data" method='post'>
  26. <div class="am-form-group am-form-file">
  27. <button type="button" class="am-btn am-btn-primary am-btn-sm">选择要上传的文件</button>
  28. <input id="doc-form-file" type="file" name="file" multiple>
  29. </div>
  30. <div id="file-list"></div>
  31. <p>
  32. <button type="submit" class="am-btn am-btn-default">提交</button>
  33. </p>
  34. </form>
  35. <p><a href="/file_review"><button class="am-btn am-btn-danger">查看全部文件</button></a></p>
  36. </div>
  37. </body>
  38. </html>

这个是文件上传的网页,界面如下:

文件上传页面

选择上传文件,完成上传后,则会显示如下界面:

文件上传成功

接着是fileReview.html,其代码如下:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>文件浏览</title>
  6. <link rel="shortcut icon" href="{{static_url('images/flower.ico')}}">
  7. <link rel="stylesheet" href="{{static_url('CSS/bootstrap.min.css')}}">
  8. <link rel="stylesheet" href="{{static_url('CSS/amazeui.min.css')}}">
  9. </head>
  10. <body>
  11. <div align="center">
  12. <br><br>
  13. <h1>文件浏览</h1>
  14. <ul class="list-group" style="width:800px;text-align:left">
  15. {% for file in files %}
  16. {% if file.endswith('.csv') or file.endswith('.xls') or file.endswith('.xlsx') %}
  17. <li class="list-group-item"> <a href={{"/data?file="+file}}>{{ file }}</a></li>
  18. {% end %}
  19. {% end %}
  20. </ul>
  21. <a href="/file"><button class="btn btn-success" id="review">文件上传界面</button></a>
  22. </div>
  23. </body>
  24. </html>

该页面主要用于显示上传的表格文件,界面如下:

查看全部文件

最后是dataReview.html,代码如下:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>数据预览</title>
  6. <link rel="shortcut icon" href="{{static_url('images/flower.ico')}}">
  7. <link rel="stylesheet" href="{{static_url('CSS/table.css')}}">
  8. <link rel="stylesheet" href="{{static_url('CSS/bootstrap.min.css')}}">
  9. </head>
  10. <body>
  11. <br><br>
  12. <div align="center">
  13. <div style="width:800px">
  14. <table class="table table-striped table-bordered table-condensed table-responsive">
  15. <thead id="index">
  16. <tr>
  17. {% for title in data[0] %}
  18. <th>{{ title }}</th>
  19. {% end %}
  20. </tr>
  21. </thead>
  22. <tbody id="body">
  23. {% for line in data[1:] %}
  24. <tr>
  25. {% for cell in line %}
  26. <td>{{ cell }}</td>
  27. {% end %}
  28. </tr>
  29. {% end %}
  30. </tbody>
  31. </table>
  32. </div>
  33. <a href="/file"><button class="btn btn-warning" id="review">文件上传界面</button></a>
  34. </div>
  35. </body>
  36. </html>

该界面主要用于显示表格文件中的数据,比如刚才上传成功的Excel文件,其中的数据如下:

表格数据预览

  仅有HTML页面是不够的,我们还需要Python代码来控制网页的运行,这就是server.py,其中的代码如下:

  1. # -*- coding: utf-8 -*-
  2. import xlrd
  3. import os.path
  4. import tornado.httpserver
  5. import tornado.ioloop
  6. import tornado.options
  7. import tornado.web
  8. from tornado.options import define, options
  9. #定义端口为12306
  10. define("port", default=12306, help="run on the given port", type=int)
  11. class UploadFileHandler(tornado.web.RequestHandler):
  12. # get函数
  13. def get(self):
  14. self.render('upload.html')
  15. # post函数
  16. def post(self):
  17. # 文件的存放路径
  18. upload_path = os.path.join(os.path.dirname(__file__), 'files')
  19. # 提取表单中‘name’为‘file’的文件元数据
  20. file_metas = self.request.files['file']
  21. for meta in file_metas:
  22. filename = meta['filename']
  23. filepath = os.path.join(upload_path, filename)
  24. # 有些文件需要已二进制的形式存储,实际中可以更改
  25. with open(filepath, 'wb') as up:
  26. up.write(meta['body'])
  27. self.write("<br><br>")
  28. self.write('<p>上传%s成功!</p>' % filename)
  29. self.write('<p><a href="/file_review"><button>查看全部文件</button></a></p>')
  30. class FileReviewHandler(tornado.web.RequestHandler):
  31. def get(self):
  32. # 文件的存放路径
  33. upload_path = os.path.join(os.path.dirname(__file__), 'files')
  34. files = os.listdir(upload_path)
  35. for file in files:
  36. if os.path.isdir(file):
  37. files.remove(file)
  38. self.render('fileReview.html', files=files)
  39. class DataReviewHandler(tornado.web.RequestHandler):
  40. def get(self):
  41. filename = self.get_argument('file')
  42. print(filename)
  43. # 文件的存放路径
  44. upload_path = os.path.join(os.path.dirname(__file__), 'files')
  45. file_path = os.path.join(upload_path, filename)
  46. if filename.endswith('.csv'):
  47. with open(file_path, "r") as f:
  48. data = f.readlines()
  49. data = [line.strip().split(',') for line in data]
  50. elif filename.endswith('.xls') or filename.endswith('.xlsx'):
  51. tables = xlrd.open_workbook(file_path)
  52. table = tables.sheets()[0] # 第一张表格
  53. nrows = table.nrows
  54. # 循环行列表数据
  55. data = []
  56. for i in range(nrows):
  57. data.append(table.row_values(i))
  58. else:
  59. data = []
  60. self.render('dataReview.html', data=data)
  61. # 主函数
  62. def main():
  63. # 开启tornado服务
  64. tornado.options.parse_command_line()
  65. # 定义app
  66. app = tornado.web.Application(
  67. handlers=[(r'/file', UploadFileHandler),
  68. (r'/file_review', FileReviewHandler),
  69. (r'/data', DataReviewHandler)
  70. ], # 网页路径控制
  71. template_path=os.path.join(os.path.dirname(__file__), "templates"), # 模板路径
  72. static_path=os.path.join(os.path.dirname(__file__), "static"), # 配置静态文件路径
  73. )
  74. http_server = tornado.httpserver.HTTPServer(app)
  75. http_server.listen(options.port)
  76. tornado.ioloop.IOLoop.instance().start()
  77. main()

点击运行server.py文件,在浏览中输入“localhost:12306/file”就能看到刚才的文件上传的页面了。
  到此,我们就讲完了这个项目的结构,我们省去了static文件的讲述,因为这并不影响程序的运行,只是页面的样式会比较丑陋,如果您想获得较好的浏览效果,可以从该项目的github地址中下载static文件夹,不必再自己重头写起。

  笔者提供了以下三种方式供读者使用该项目:

  • 直接使用
  • github使用
  • docker使用

  读者按照上面的讲解,自己写一个项目,拷贝static文件夹,然后点击运行server.py,在浏览中输入“localhost:12306/file”就能使用该程序来浏览上传的表格了。

  从该项目的github地址:https://github.com/percent4/csv_file_review 中下载该项目,命令如下:

  1. git init
  2. git clone https://github.com/percent4/csv_file_review

然后安装必要的第三方模块:xlrd, tornado, 点击运行server.py,在浏览中输入“localhost:12306/file”就能使用该程序来浏览上传的表格了。

  首先拉取docker镜像:

  1. docker pull jclian91/dockertest:csv_file_review.2019.02.21.2312

然后运行该镜像:

  1. docker run -p 12306:12306 -v $PWD/db:/root/csv_file_review/src/files -it c97f252cd6e8 bash

注意, -it后面为刚才拉取的docker镜像的ID,需要将ID替换为你刚拉取的镜像ID,运行端口为本机的12306,上传的表格数据存放在$PWD/db路径下。进入虚拟机后,运行server.py即可启动服务,

  1. [root@fbb2c3fb6ce1 src]# ls
  2. __init__.py files server.py static templates
  3. [root@fbb2c3fb6ce1 src]# python server.py

在浏览中输入“localhost:12306/file”就能使用该程序来浏览上传的表格了。

  关于本项目的介绍就到这儿了,感谢大家阅读~
  如您对本项目的源代码感兴趣,可参考网址:https://github.com/percent4/csv_file_review

注意:本人现已开通微信公众号: Python爬虫与算法(微信号为:easy_web_scrape), 欢迎大家关注哦~~

版权声明:本文为jclian91原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/jclian91/p/10417037.html