Python 实现 Filebrowser

Python 实现 Filebrowser

异步IO实现,HTTP1.0, 200,404,405等信息。实现GET,HEAD, POST方法

一、 代码实现

FileBrowser.py

p# -*- coding: utf-8 -*-
# @File    : FileBrowser.py
# @Author  : zy
import argparse
import asyncio
import urllib.parse
import mimetypes
import os, json, time

html404 = b'<html><head><title>404 Not Found</title></head><body><center><h1>404 Not Found</h1></center></body></html>'
html405 = b'<html><head><title>405 Method Not Found</title></head><body><center><h1>405 Method Not Found</h1></center></body></html>'


async def dispatch(reader, writer):
    try:
        data = await reader.readline()
        if data == b'\r\n':
            return
        message = data.decode().split(' ')
        print(message)  # ['GET', '/', 'HTTP/1.1\r\n']
        # message[0] method
        # message[1] dir
        if message[1] == "./favicon.ico":
            return

        if message[0] == "GET":  # Method GET returns 200 response.
            dir_path = urllib.parse.unquote(message[1])
            if dir_path[0] != '/':
                dir_path = '/' + dir_path[0]
            relative_path = root_dir + dir_path
            print(relative_path)
            if os.path.isfile(relative_path):  # open the file and guess the mimetype.
                mimetype = mimetypes.guess_type(relative_path)[0]
                if mimetype is None:
                    mimetype = 'application/octet-stream'
                httpresponse = [b'HTTP/1.0 200 OK\r\n',
                                bytes('Content-Type:', encoding='UTF-8') +
                                bytes(mimetype + '; charset=utf-8\r\n', encoding='UTF-8'),
                                bytes('Content-Length: ' + str(os.path.getsize(relative_path)) + '\r\n',
                                      encoding="UTF-8"),
                                b'\r\n']
                file = open(relative_path, 'rb')
                httpresponse.append(file.read())
                writer.writelines(httpresponse)
            elif os.path.isdir(relative_path):  # homepage
                httpresponse = [b'HTTP/1.0 200 OK\r\n',
                                b'Content-Type:text/html; charset=utf-8\r\n',
                                b'Connection: close\r\n', b'\r\n',
                                bytes('<html><head><title>Index of ' + relative_path + '</title></head><body>\r\n',
                                      encoding="UTF-8"),
                                bytes('<div style="position:relative;"><img src="https://www.sustech.edu.cn/wp-content/uploads/%E6%A0%A1%E5%8E%86-1.jpg?id=8835261" width="100%"height="30%"></div><div style="position:absolute; left:80px; top:50px; "><img src="https://www.sustech.edu.cn/wp-content/themes/twentyseventeen/images/sustech-logo-cn.png" width="433" height="86"/></div>',encoding='UTF-8'),
                                bytes('<h1>Index of ' + relative_path + '</h1><hr><ul>\r\n', encoding='UTF-8'),
                                bytes('<li><a href="../">..</a></li><br>\r\n', encoding='UTF-8')]
                dirlist = os.listdir(relative_path)
                print(dirlist)
                for i in range(len(dirlist)):
                    if os.path.isfile(dirlist[i]):  # file
                        httpresponse.append(
                            bytes('<li><a href="' + dirlist[i] + '">' + dirlist[i] + "</a></li><br>\r\n",
                                  encoding='UTF-8'))
                    else:  # directory
                        httpresponse.append(
                            bytes('<li><a href="' + dirlist[i] + '/">' + dirlist[i] + '</a></li><br>\r\n',
                                  encoding='UTF-8'))
                httpresponse.append(bytes('</ul><hr></body></html>', encoding='UTF-8'))
                writer.writelines(httpresponse)
            else:  # Not existing file or directory returns 404 response.
                writer.writelines([
                    b'HTTP/1.0 404 Method Not Found\r\n',
                    b'Content-Type:text/html; charset=utf-8\r\n',
                    b'Connection: close\r\n',
                    b'\r\n',
                    html404,
                    b'\r\n'
                ])
            await writer.drain()
            writer.close()

        elif message[0] == "HEAD":  # Method HEAD returns 200 response and the head of http response if such dir exists .
            dir_path = urllib.parse.unquote(message[1])
            if dir_path[0] != '/':
                dir_path = '/' + dir_path[0]
            relative_path = root_dir + dir_path
            print(relative_path)
            if os.path.isfile(relative_path):  # Add mimetype to the http header if the path is a file.
                mimetype = mimetypes.guess_type(relative_path)[0]
                if mimetype is None:
                    mimetype = 'application/octet-stream'
                httpresponse = [b'HTTP/1.0 200 OK\r\n',
                                bytes('Content-Type:', encoding='UTF-8') +
                                bytes(mimetype + '; charset=utf-8\r\n', encoding='UTF-8'),
                                bytes('Content-Length: ' + str(os.path.getsize(relative_path)) + '\r\n',
                                      encoding="UTF-8"),
                                b'\r\n']
                writer.writelines(httpresponse)
            elif os.path.isdir(relative_path):  # Edit the http header of a directory
                httpresponse = [b'HTTP/1.0 200 OK\r\n',
                                b'Content-Type:text/html; charset=utf-8\r\n',
                                b'Connection: close\r\n', b'\r\n',
                                ]
                writer.writelines(httpresponse)
            else:  # Not existing file or directory returns 404 response.
                writer.writelines([
                    b'HTTP/1.0 404 Method Not Found\r\n',
                    b'Content-Type:text/html; charset=utf-8\r\n',
                    b'Connection: close\r\n',
                    b'\r\n',
                    html404,
                    b'\r\n'
                ])
            await writer.drain()
            writer.close()

        elif message[0] == "POST":  # Method POST returns 405 response.
            writer.writelines([
                b'HTTP/1.0 405 Method Not Allowed\r\n',
                b'Content-Type:text/html; charset=utf-8\r\n',
                b'Connection: close\r\n',
                b'\r\n',
                html405,
                b'\r\n'
            ])
            await writer.drain()
            writer.close()

        else:  # Other method returns 405 response.
            writer.writelines([
                b'HTTP/1.0 405 Method Not Allowed\r\n',
                b'Content-Type:text/html; charset=utf-8\r\n',
                b'Connection: close\r\n',
                b'\r\n',
                html405,
                b'\r\n'
            ])
            await writer.drain()
            writer.close()
    except ConnectionError:
        pass


if __name__ == '__main__':
    # python FileBrowser.py --port 8000 --dir ~/
    parser = argparse.ArgumentParser(description='Simple Web File Browser')
    parser.add_argument('--port', type=int, default=8080,
                        help='an integer for the port of the simple web file browser')
    parser.add_argument('--dir', type=str, default="./",
                        help='The Directory that the browser should display for home page')
    args = parser.parse_args()
    loop = asyncio.get_event_loop()
    coro = asyncio.start_server(dispatch, '127.0.0.1', port=args.port, loop=loop)
    server = loop.run_until_complete(coro)
    root_dir = args.dir
    if root_dir[-1] == '/':
        root_dir = root_dir[:-1]
    print("server run at port %d" % args.port)
    print("server run at dir %s" % args.dir)
    print('Serving on {} and Hit Ctrl + C to end the server'.format(server.sockets[0].getsockname()))
    try:
        loop.run_forever()
    except KeyboardInterrupt:
        exit()
    server.close()
    loop.run_until_complete(server.wait_closed())
    loop.close()

  • 在terminal中运行py文件,指定端口和路径:
    python3 FileBrowser.py --port 8080 --dir ~/
  • 实例:
    在这里插入图片描述
  • 打开浏览器看看效果:(自己随便加了个图片)
    在这里插入图片描述
    已知MIME TYPE 打开文件并以HTML文件展示在浏览器,例如打开FileBrowser.py
    在这里插入图片描述
    未知MIME Type 会下载到本地:
    在这里插入图片描述
    进入文件夹后可以通过.. 返回上级目录:
    在这里插入图片描述
    访问不存在的文件,如在地址栏中输入URL:
    在这里插入图片描述
    则会报出404页面:
    在这里插入图片描述
    HEAD 方法测试:
    在这里插入图片描述
    POST 返回405:
    在这里插入图片描述

二、emm

cmd 输入 python -m http.server 就可以实现当前文件夹的file browser。
例如:
在这里插入图片描述
在这里插入图片描述

  • emm,这不啥也有了吗(404 也有。。。)
    在这里插入图片描述

三、总结

  • 需要了解HTTP报文结构:
    结构其实都是:

注意blank line 和 crlf 都不可以少。(\r\n)

在这里插入图片描述

  • 需要自学点HTML(Message body内部)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值