Project introduction

In this article, I will introduce one of my projects, which mainly uses Tornado to implement the preview of table files, which can be browsed to support CSV and Excel files. The preview screen is as follows:

We will see how this functionality is achieved through Tornado below.


The code structure of the project is shown below:

It is mainly divided into four parts:

  • files
  • static
  • templates
  • Py code

The files folder is where the files are stored. The static folder is the front-end static file, which you can download from the project’s GitHub (see below for the download address). The templates folder is mainly for HTML files, and the py file is used for back-end control.

First, let’s look at three HTML files. First, upload.

<! DOCTYPE HTML > < HTML lang="en"> <head> <meta charset=" utf-8 "> </title> <link rel="shortcut icon" href="{{static_url('images/flower.ico')}}"> <link rel="stylesheet" href="{{static_url('CSS/amazeui.min.css')}}"> <script  src="{{static_url('JS/amazeui.min.js')}}"></script> <script> $(function() { $('#doc-form-file').on('change', function() { var fileNames = ''; $.each(this.files, function() { fileNames += '<span class="am-badge">' + + '</span> '; }); $('#file-list').html(fileNames); }); }); </script> </head> <body> <div align="center" <br><br> <h1> </h1> <form action='file' enctype="multipart/form-data"  method='post'> <div class="am-form-group am-form-file"> <button type="button" class="am-btn am-btn-primary Am-btn-sm "> </button> <input id="doc-form-file" type="file" name="file" multiple> </div> <div Id = "file - list" > < / div > < p > < button type = "submit" class = "am - BTN am - BTN - the default" > submit < / button > < / p > < / form > < p > < a Href = "/ file_review" > < button class = "am - BTN am - BTN - danger" > view all files < / button > < / a > < / p > < / div > < / body > < / HTML >

This is the page for uploading files. The interface is as follows:

Select the file to upload. After uploading, the following interface will be displayed:

Next is FileReview.html, which looks like this:

<! DOCTYPE HTML > < HTML lang="en"> <head> <meta charset=" utf-8 "> </title> <link rel=" Shortcut icon" href="{{static_url('images/flower.ico')}}"> <link rel="stylesheet" href="{{static_url('CSS/bootstrap.min.css')}}"> <link  rel="stylesheet" href="{{static_url('CSS/amazeui.min.css')}}"> </head> <body> <div align="center"> <br><br> </ span > </ p > < p class="list-group" style="width:800px; text-align:left"> {% for file in files %} {% if file.endswith('.csv') or file.endswith('.xls') or file.endswith('.xlsx')  %} <li class="list-group-item"> <a href={{"/data? file="+file}}>{{ file }}</a></li> {% end %} {% end %} </ul> <a href="/file"><button class="btn btn-success" Id = "review" > file upload interface < / button > < / a > < / div > < / body > < / HTML >

This page is mainly used to display the uploaded form file. The interface is as follows:

Finally, the datareview.html code looks like this:

<! DOCTYPE HTML > < HTML > <head> <meta charset=" utf-8 "> </title> <link rel=" Shortcut shortcut" href="{{static_url('images/flower.ico')}}"> <link rel="stylesheet" href="{{static_url('CSS/table.css')}}"> <link rel="stylesheet" href="{{static_url('CSS/bootstrap.min.css')}}"> </head> <body> <br><br> <div align="center"> <div style="width:800px"> <table class="table table-striped table-bordered table-condensed table-responsive"> <thead id="index"> <tr> {% for title in data[0] %} <th>{{ title }}</th> {% end %} </tr> </thead> <tbody id="body"> {% for line in data[1:] %} <tr> {% for cell in line %} <td>{{ cell }}</td> {% end %} </tr> {% end %} </tbody> </table> </div> <a Href ="/file"><button class=" BTN btn-warning" id="review"> </button></a> </div> </body> </ HTML >

This interface is mainly used to display the data in the table file, such as the Excel file that was uploaded successfully just now. The data are as follows:

HTML pages are not enough, we also need Python code to control the running of the web page. This is, which has the following code:

# -*- coding: utf-8 -*- import xlrd import os.path import tornado.httpserver import tornado.ioloop import tornado.options import Tornado. Web from Tornado. Options import define, options # define("port", default=12306, Help = "run on the given port", type = int) class UploadFileHandler (tornado. Web. RequestHandler) : # get function def get (self) : Render ('upload.html') # post def post(self): Upload_path = os.path.join(os.path.dirname(__file__)), File_metas = self.request. Files ['file'] for meta in file_metas: file_metas = self.request. Files ['file'] for meta in file_metas: FileName = Meta [' fileName '] filePath = os.path.join(upload_path, fileName) With open(filePath, 'wb') as up: up.write(meta['body']) self.write("<br><br>") self.write('<p> upload %s! < / p > '% filename) self. Write (' < p > < a href = "/ file_review" > < button > see all files < / button > < / a > < / p >') class FileReviewHandler(tornado.web.RequestHandler): def get(self): Upload_path = os.path.join(os.path.dirname(__file__)), 'files') files = os.listdir(upload_path) for file in files: if os.path.isdir(file): files.remove(file) self.render('fileReview.html', files=files) class DataReviewHandler(tornado.web.RequestHandler): def get(self): Filename = self. Get_argument (' file ') print (filename) # file storage path upload_path = OS. The path. The join (OS) path) dirname (__file__), 'files') file_path = os.path.join(upload_path, filename) if filename.endswith('.csv'): with open(file_path, "r") as f: data = f.readlines() data = [line.strip().split(',') for line in data] elif filename.endswith('.xls') or filename.endswith('.xlsx'): Tables = xlrd.open_workbook(file_path) table = Tables. Sheets ()[0] # NROWS = Tables. Sheets ( in range(nrows): data.append(table.row_values(i)) else: Data = [] self.render(' datareview.html ', data=data) # def main(): App = nado.web.Application(Handlers =[(r'/file', Handlers =[(r'/file', UploadFileHandler), (r'/file_review', FileReviewHandler), (r'/data', DataReviewHandler) ], Template_path =os.path.join(os.path.dirname(__file__), "templates"), # static_path=os.path.join(os.path.dirname(__file__), "static"), # configuration file path) static http_server = tornado. Httpserver. Httpserver (app) http_server. Listen (options. The port) tornado.ioloop.IOLoop.instance().start() main()

Run the file and type “localhost: 12306./ file” in the browser to see the page where the file was uploaded. This is the end of the structure of the project. We have omitted the static file description, because it does not affect the execution of the program, but the page style will be ugly. If you want a better browsing effect, you can download the static folder from the project’s GitHub address and do not have to start from scratch.


The author offers the following three ways for readers to use the project:

  • Direct use of
  • Making use of
  • Docker use
Direct use of

To browse the uploaded table, click Run and type “localhost:12306/file” in Browse.

Making use of

From the project making address:… , the command is as follows:

git init
git clone

Then install the necessary third party modules: XLRD, Tornado, click Run and type “localhost:12306/file” in Browse to browse the uploaded form using this program.

Docker use

First pull the Docker image:

Docker pull jclian91 / dockertest: csv_file_review 2019.02.21.2312

Then run the image:

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

Note: -it is the ID of the docker image you just pulled. You need to replace the ID with the image ID you just pulled. The port to run is 12306 on the native. After entering the virtual machine, run to start the service.

[root@fbb2c3fb6ce1 src]# ls  files  static  templates
[root@fbb2c3fb6ce1 src]# python

To browse the uploaded form, type “localhost:12306/file” in Browse.


About the project is introduced here, thank you for your reading ~ if you interest in this project’s source code, can refer to the website:…

Note: I have opened WeChat public account: Python crawler and algorithm (WeChat ID: easy_web_scrape), welcome to pay attention to oh ~~