热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

linux预览md文件_利用Tornado搭建文档预览系统

在平时的工作或学习中,我们经常会接触不同格式的文档类型,比如txt,log,Offices文档,编程代码脚本&
在平时的工作或学习中,我们经常会接触不同格式的文档类型,比如txt,log,Offices文档,编程代码脚本,图片,视频等。本文将会介绍笔者的一个朴素想法,即把不同格式的文档都放在同一个平台中进行预览,这样既方便查看常见文档,又能提升工作和学习效率。本项目的工程结构如下:
63029ea445ccc1e0a2881777af997f81.png项目结构
本项目现在已支持8种文档格式的格式,分别为:
  • text/html: 如html文件等;
  • text/plain: 如txt/log文件等;
  • text/csv: csv文件;
  • application/json: json文件;
  • application/pdf: pdf文件;
  • text/x-python: Python脚本文件;
  • image/*: 各种图片文件,比如jpg, png等;
  • markdown文件

准备工作

首先,我们需要下载前端的PDF预览JS框架PDF.js,它是一个网页端的PDF文件解析和预览框架,下载网址为:http://mozilla.github.io/pdf.js/ 。接着,本项目还用到了showdown.js,该JS框架用于渲染Markdown文档。用Python做后端,tornado为web框架,笔者使用的版本为5.1.1。

项目代码

我们下载PDF.js项目代码,并在/pdfjs/web目录下新建files文件夹,用于存放上传的文件。为了能够用PDF.js实现PDF文件预览,需要切换至pdfjs文件夹,运行搭建文件服务器命令:

python -m http.server 8081或者:

python -m SimpleHTTPServer 8081接着介绍HTML文件,index.html是首页代码,主要实现文件上传功能,代码如下:

文件上传

文件上传 提交
页面如下(有点儿过于简单,还好本项目是注重文档预览功能):
3ce92d1141ca49452d269d3487a805d0.png文件上传页面
markdown.html主要用于展示Markdown文件中的内容,代码如下:

Markdown文件展示 function convert(){ var converter = new showdown.Converter(); var text = "{{ md_content }}"; var html = converter.makeHtml(text.replace(/newline/g, "\n")); document.getElementById("result").innerHTML = html; }注意,我们在head部分引用了showdown.js的CDN地址,这样就不用下载该项目文件了。最后是后端部分,采用Python的Tornado模块实现。tornado_file_receiver.py主要用于文档的上传和保存,并展示文档内容,完整代码如下:

# -*- coding: utf-8 -*-import osimport loggingimport tracebackimport tornado.ioloopimport tornado.webfrom tornado import optionsfrom parse_file import *# 文档上传与解析class UploadFileHandler(tornado.web.RequestHandler): # get函数 def get(self): self.render('upload.html') def post(self): # 文件的存放路径 upload_path = os.path.join(os.path.dirname(__file__), 'pdfjs/web/files') # 提取表单中‘name’为‘file’的文件元数据 # 暂时只支持单文档的上传 file_meta = self.request.files['file'][0] filename = file_meta['filename'] # 保存文件 with open(os.path.join(upload_path, filename), 'wb') as up: up.write(file_meta['body']) text = file_meta["body"] # 解析文件的内容 mtype = file_meta["content_type"] logging.info('POST "%s" "%s" %d bytes', filename, mtype, len(text)) if mtype in ["text/x-python", "text/x-python-script"]: self.write(parse_python(str(text, encoding="utf-8"))) elif mtype in ["text/plain", "text/csv"]: self.write(parse_text_plain(str(text, encoding="utf-8"))) elif mtype == "text/html": self.write(str(text, encoding="utf-8")) elif mtype.startswith("image"): self.write(parse_image(mtype, text)) elif mtype == "application/json": self.write(parse_application_json(str(text, encoding="utf-8"))) elif mtype == "application/pdf": self.redirect("http://127.0.0.1:8081/web/viewer.html?file=files/%s" % filename) elif mtype == "application/octet-stream" and filename.endswith(".md"): self.render("markdown.html", md_content=r"%s" % str(text, encoding="utf-8").replace("\n", "newline")) else: # 其余文件格式 try: self.write(str(text, encoding="utf-8").replace("\n", "
"))
except Exception: logging.error(traceback.format_exc()) self.write('')def make_app(): return tornado.web.Application([(r"/file", UploadFileHandler)], template_path=os.path.join(os.path.dirname(__file__), "templates")) # 模板路径if __name__ == "__main__": # Tornado configures logging. options.parse_command_line() app = make_app() app.listen(8888) tornado.ioloop.IOLoop.current().start()
parse_file.py用于解析各种格式的文档,并返回HTML展示的格式,完整代码如下:

# -*- coding: utf-8 -*-# author: Jclian91# place: Pudong Shanghai# time: 2020/6/5 1:05 下午# filename: parse_file.py# 用于解析各种文件类型的数据import jsonimport base64import loggingimport tracebackfrom json import JSONDecodeError# 解析text/plain或者text/csv文件格式def parse_text_plain(text): return "%s" % text.replace("\n", "
")
# 解析application/json文件格式def parse_application_json(text): try: data_dict = json.loads(text) return json.dumps(data_dict, ensure_ascii=False, indent=2).replace("\n", "
").replace(" ", " ")
except JSONDecodeError: try: data_list = [json.loads(_) for _ in text.split("\n") if _] return json.dumps(data_list, ensure_ascii=False, indent=2).replace("\n", "
").replace(" ", " ")
except JSONDecodeError: logging.error(traceback.format_exc()) return "JSON文件格式解析错误" except Exception as err: logging.error(traceback.format_exc()) return "未知错误: %s" % err# 解析image/*文件格式def parse_image(mtype, text): return '' % \ (mtype, str(base64.b64encode(text), "utf-8"))# 解析Python文件def parse_python(text): # indent和换行 text = text.replace("\n", "
").replace(" ", " ").replace("\t", " " * 4)
# 关键字配色 color_list = ["gray", "red", "green", "blue", "orange", "purple", "pink", "brown", "wheat", "seagreen", "orchid", "olive"] key_words = ["self", "from", "import", "def", ":", "return", "open", "class", "try", "except", '"', "print"] for word, color in zip(key_words, color_list): text = text.replace(word, '' % (color, word)) colors = ["peru"] * 7 punctuations = list("[](){}#") for punctuation, color in zip(punctuations, colors): text = text.replace(punctuation, '' % (color, punctuation)) html = "%s" % text return html

实现方式

下面将进一步介绍各种格式实现预览的机制。

text/html: 如html文件等

html文件的MIMETYPE为text/html,由于本项目采用HTML展示,因此对于text/html的文档,直接返回其内容就可以了。从Tornado的代码中我们可以看出,filename变量为文档名称,text为文档内容,bytes字符串。在前端展示的时候,我们返回其文档内容:

self.write(str(text, encoding="utf-8"))其中,str(text, encoding="utf-8")是将bytes字符串转化为UTF-8编码的字符串。

text/plain: txt/log文件等

txt/log等文件的MIMETYPE为text/plain,其与HTML文档的不同之处在于,如果需要前端展示,需要在返回的字符中添加HTML代码,如下(parse_file.py中的代码):

# 解析text/plain或者text/csv文件格式def parse_text_plain(text): return "%s" % text.replace("\n","
")

text/csv: csv文件

csv格式文件的MIMETYPE为text/csv,其预览的方式与txt/log等格式的文档一致。但csv是逗号分隔文件,数据格式是表格形式,因此在前端展示上应该有更好的效果。关于这一格式的文档,其前端预览的更好方式可以参考文章:利用tornado实现表格文件预览。

application/json: json文件

关于json文件的预览,笔者更关注的是json文件的读取。这里处理两种情况,一种是整个json文件就是json字符串,另一种情况是json文件的每一行都是json字符串。在前端展示的时候,采用json.dumps中的indent参数实现缩进,并转化为html中的空格,实现方式如下(parse_file.py中的代码):

# 解析application/json文件格式def parse_application_json(text): try: data_dict = json.loads(text) return json.dumps(data_dict, ensure_ascii=False, indent=2).replace("\n", "
").replace(" ", " ")
except JSONDecodeError: try: data_list = [json.loads(_) for _ in text.split("\n") if _] return json.dumps(data_list, ensure_ascii=False, indent=2).replace("\n", "
").replace(" ", " ")
except JSONDecodeError: logging.error(traceback.format_exc()) return "JSON文件格式解析错误" except Exception as err: logging.error(traceback.format_exc()) return "未知错误: %s" % err
笔者相信一定有json文件更好的前端展示方式,这里没有采用专门处理json的JS框架,这以后作为后续的改进措施。

application/pdf: pdf文件

PDF文档的展示略显复杂,本项目借助了PDF.js的帮助,我们需要它来搭建PDF预览服务,这点在上面的项目代码部分的开头已经讲了。搭建好PDF预览服务后,由于上传的文件都会进入pdfjs/web/files目录下,因此PDF文档预览的网址为:http://127.0.0.1:8081/web/viewer.html?file=files/pdf_name ,其中pdf_name为上传的PDF文档名称。有了这个PDF预览服务后,我们展示PDF文档的代码就很简单了(tornado_file_receiver.py中的代码):

elif mtype == "application/pdf": self.redirect("http://127.0.0.1:8081/web/viewer.html?file=files/%s" % filename)

text/x-python: Python脚本文件

Python脚本的处理方式并不复杂,无非是在把Python文档转化为HTML文件格式的时候,加入缩进、换行处理,以及对特定的Python关键字进行配色,因此代码如下(parse_file.py中的代码):

# 解析Python文件def parse_python(text): # indent和换行 text = text.replace("\n", "
").replace(" ", " ").replace("\t", " " * 4)
# 关键字配色 color_list = ["gray", "red", "green", "blue", "orange", "purple", "pink", "brown", "wheat", "seagreen", "orchid", "olive"] key_words = ["self", "from", "import", "def", ":", "return", "open", "class", "try", "except", '"', "print"] for word, color in zip(key_words, color_list): text = text.replace(word, '' % (color, word)) colors = ["peru"] * 7 punctuations = list("[](){}#") for punctuation, color in zip(punctuations, colors): text = text.replace(punctuation, '' % (color, punctuation)) html = "%s" % text return html
根据笔者的了解,其实有更好的Python脚本内容的预览方式,可以借助handout模块实现,这点笔者将会在后续加上。

image/*: 各种图片文件,比如jpg, png等

图片文件在HTML上的展示有很多中,笔者采用的方式为:

就是对图片读取后的字符串进行base64编码即可,因此实现代码如下(parse_file.py中的代码):

import base64# 解析image/*文件格式def parse_image(mtype, text): return '' % \ (mtype, str(base64.b64encode(text), "utf-8"))

markdown文件

markdown文件的预览稍显复杂,借助showdown.js和不断的尝试探索,由于markdown在读取后的换行符\n在转化为Javascript字符串时并不需要转义,这是实现预览的难点。笔者的做法是把Python读取的markdown中的换行符\n转化为newline,并在JS渲染的时候才把newline替换成\n,这就解决了不需要转移的难题。具体的实现可以参考markdown.html,现在Python后端代码中把Python读取的markdown中的换行符\n转化为newline,代码如下:

elif mtype == "application/octet-stream" and filename.endswith(".md"): self.render("markdown.html", md_content=r"%s" % str(text, encoding="utf-8").replace("\n", "newline"))接着在markdown.html中的JS部分把Python读取的markdown中的换行符\n转化为newline,代码如下:

function convert(){ var converter = new showdown.Converter(); var text = "{{ md_content }}"; var html = converter.makeHtml(text.replace(/newline/g, "\n")); document.getElementById("result").innerHTML = html; }

效果demo

下面将给出上述8中文档格式在本系统中的预览效果。

text/html: 如html文件等

上传文件为reponse.html,预览效果如下:
bc32d2c1a54fa69641fbc2c53224cc8f.pnghtml文件预览示例

text/plain: txt/log文件等

上传文件为info.log,预览效果如下:
d9281f1c9a7f92c74ec5a233f805ebf0.pnginfo.log文件预览

text/csv: csv文件

上传文件为iris.csv,预览效果如下:
f0f1f077f1bc696d3d2c205b2b2fa277.pngiris.csv文件预览

application/json: json文件

上传文件为test1.json,预览效果如下:
e8ea8d4f456c9a4f05186b6fbe0a7bdc.pngtest1.json文件预览

application/pdf: pdf文件

上传文件为,预览效果如下:
694b1d16a2b0e7e41c66e86dd9fb7738.pngPDF文档预览

text/x-python: Python脚本文件

上传文件为test.py,预览效果如下:
5d8b71315046c43410bbfcd47e3f7452.pngPython脚本预览

image/*: 各种图片文件,比如jpg, png等

上传图片为ffe3d40029eae71ccf8587e5dc21d58d.jpg,预览效果如下:
75eca7b85a4bbc8b233f184754aeb10b.pngjpg图片预览

markdown文件

传文件为Scrapy爬取动态网页.md,预览效果如下:

a173a203096ef2eea6025e1890e37bf9.pngmarkdown文件预览

文件上传记录

为了证明上面的预览确实是笔者已经实现的,而不是从哪搬来的图片,特放上程序运行记录以及files目录下的文件,如下:
d3985574b2e8e0c92f24f1254a12c19c.png文件上传记录
c97f5b3885cf7896a6d98e929b3fff4f.png上传文件

总结

本项目已经开源至Github,网址为https://github.com/percent4/document_reviewer 本项目现在支持的文档格式还比较少,后续可以增加更好文档格式的支持,另外,现在的文档格式的预览有些可以做得更好,后续也会进行优化~感谢大家阅读,希望读者多多批评指正~

参考文档

  1. PDF.js官方网址:http://mozilla.github.io/pdf.js/

  2. showdown.js官方网址:https://github.com/showdownjs/showdown

  3. 让你的站点也支持Markdown——showdown.js使用教程:https://www.jianshu.com/p/747d6f8dddb0

-END-

已有50万人
领取Python案例实战课

46b235b80c4243be04c26466e61f6bf6.png

世界正在奖励坚持学习的人!



推荐阅读
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
  • HTML学习02 图像标签的使用和属性
    本文介绍了HTML中图像标签的使用和属性,包括定义图像、定义图像地图、使用源属性和替换文本属性。同时提供了相关实例和注意事项,帮助读者更好地理解和应用图像标签。 ... [详细]
author-avatar
静心-苑
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有