还在用Python自带的httpserver?快开感受下更炫酷的Vip版功能吧!

python HttpServer

python2与python3都可以基于SimpleHTTPServer,快速创建一个http服务器,但方法略有不同。
首先进入你需要设置的http服务器目录 (我以自己电脑路径:F:/Working~Study) ,即进入到该目录下,然后:

  • python2: python -m SimpleHTTPServer 8888
  • python3: python -m http.server 8888

使用方式与样式都是一样的,如下图:


python自带httpserver.gif

用起来没问题,但丑出天际...
提单时间到,来说一说有哪些存在的问题吧:

  1. 启动服务器后,无登陆限制,任何人都能访问
  2. 访问链接后,显示纯html页面,美观性差,或者说毫无美感可言
  3. 非ansi码的文本打开,都是乱码
  4. 文本与pdf等文件点击时,默认打开而非下载
  5. 文件夹与文件的差别仅仅在于是否有末尾/,识别度差
  6. 文件夹与文件的详细信息无法获取(如:创建时间,大小)
  7. 页面点击无返回按钮,只能使用浏览器默认的前进后退
  8. 默认的http只有下载,而没有上传功能(这个是硬伤啊!)

既然python自带的http服务器,存在这么多的问题,那决不能惯着它,今天咱们就自己重写一个PythonHttpServer

FlaskHttpServer

先来看看最终的实现效果:


FlaskHttpServer.gif
  • 安全
    添加了用户名密码的登陆限制(简单写死了用户名密码,可扩展支持数据库读取等方式),这个就不多说了
  • 样式
    引入了bootstrap的表单样式,简洁美观
  • 下载
    设置所有文件均直接下载,解决了之前文本等直接打开、并且乱码的问题
  • 展示
    1. 仿照windows系统,添加了名称、修改时间、文件类型、大小
    2. 优化了文件夹、文件等展示方式,并针对两者进行大小写的模糊排序,
    3. 针对文件大小,优化动态展示B、KB、MB、GB
  • 页面跳转
    增加了首页,与子路径的快捷键访问,每一层的路径均可做为链接进行跳转
设计方案
  1. 使用蓝图构建项目
    虽然目前仅存在账户管理与页面展示和下载两个模块,但使用蓝图的目的是为了便于扩展,后期有空了还可以实现下上传功能。
    整体目录如下:


    项目目录
  2. 针对目录展示
    获取path后,先获取os.listdir()结果进行排序:
    sorted(os.listdir('.'), key=lambda x: x.lower())
    再将目录分为两个列表(文件夹、文件),并针对类型不同,分别获取不同数据,方法如下:

class DocumentReader:
    def __init__(self, real_path):
        self.real_path = real_path

    def analysis_dir(self):
        dirs = []
        files = []
        os.chdir(self.real_path)
        for name in sorted(os.listdir('.'), key=lambda x: x.lower()):
            _time = time.strftime("%Y/%m/%d %H:%M", time.localtime(os.path.getctime(name)))
            if os.path.isdir(name):
                dirs.append([name, _time, '文件夹', '-'])
            elif os.path.isfile(name):
                file_type = os.path.splitext(name)[1]
                size = self.get_size(os.path.getsize(name))
                files.append([name, _time, file_type, size])
        return dirs, files

    @staticmethod
    def get_size(size):
        if size < 1024:
            return '%d  B' % size
        elif 1024 <= size < 1024 * 1024:
            return '%.2f KB' % (size / 1024)
        elif 1024 * 1024 <= size < 1024 * 1024 * 1024:
            return '%.2f MB' % (size / (1024 * 1024))
        else:
            return '%.2f GB' % (size / (1024 * 1024 * 1024))
  1. 在app中创建自定义过滤器,将所有路径进行拆分,生成子路径及对应的path进行跳转
    @app.template_filter("split_path")
    def split_path(path):
        path_list = path.split('/')
        path_list = [[path_list[i - 1], '/'.join(path_list[:i])] for i in range(1, len(path_list)+1)]
        return path_list

因为涉及的文件比较多,就不一个个的往上贴了,如果大家对这个小项目感兴趣,可以公众号回复关键字[服务器]获取源码....

上传功能之模态框

使用bootstrap实现点击按钮弹出窗口,简直不要太简单。我们只需要将写好的窗口内容隐藏,然后调用bootstrap的框架即可,简单几行就能完成相关功能实现....
前提条件是,我们需要引入bootstrap.min.js,直接上代码看下准备好的上传文件弹框吧....

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"> 
    <title>Bootstrap 实例 - 模态框(Modal)插件</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>

<h2>创建模态框(Modal)</h2>
<!-- 按钮触发模态框 -->
<button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
    文件上传
</button>
<!-- 模态框(Modal) -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title" id="myModalLabel">
                    请选择所需上传的本地文件
                </h4>
            </div>
            <div class="modal-body">
                <form id="upload-form" enctype="multipart/form-data">
                    <input id='file' class="btn btn-info" name="upload_file" type="file">
                </form>
            </div>
            <div class="modal-footer">
                <button id='upload' class="btn btn-primary ">上传</button>
                <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
            </div>
        </div><!-- /.modal-content -->
    </div><!-- /.modal -->
</div>
</body>
</html>
bootstrap模态框.gif
jQuery事件与ajax

正常情况下,我们使用form表单进行上传文件,需要在表单内部添加一个type="submit"的按钮,可如何才能像demo示例中的,将上传按钮置于页面的任何位置来控制上传呢?有jQuery在,就很简单...

<script>
$('#upload')
    .click(function() {
        $('#upload').submit();
    })
</script>

由于是弹出窗口,我们选择文件后,点击上传,此时如果使用url_for()进行页面跳转,有些不符合使用习惯,那么再加深一点,引入ajax进行异步提交好了,那么全量的点击事件就变为:

<script>
$('#upload').click(function() {
    var upload_path = $('#upload_path').text();
    var formData = new FormData($('#upload-form')[0]);
    formData.append("upload_path", upload_path);
    $.post({
        url: '/upload',
        dataType: 'json',
        type: 'POST',
        data: formData,
        async: true,
        cashe: false,
        contentType: false,
        processData: false,
        success: function(returndata) {
            if (returndata['code'] == 200) {
                var info = returndata['info']
                alert(info);
            }
        },
        error: function(returndata) {
            alert("上传失败!")
        }
    })
});
</script>
关于js中使用Jinjia2

在js中直接使用jinjia2的模板引擎会报错...比如这样:alert({{Book}});,那么该怎么处理?

  • bad
    将内容写在html中,然后通过js去获取:
<p id="upload_path" style="display:none">{{path}}</p>
var upload_path = $('#upload_path').text();
  • good
    通过jinjia2的tojson过滤器,可以将变量转为json字符串
    var upload_path = {{path|tojson|safe}};
最终上传实现

软件整体效果如下:


Flask_Httpserver.gif
The End

今天的内容就到这里,欢迎关注我的微信公众号【清风Python】谢谢。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容