使用Python http.server搭建文件下载/上传的HTTP服务器

动机:笔者需测试bs架构下的文件上传与下载性能,故想通过Python搭建http服务器并实现客户端与服务器之间的文件上传和下载需求

难点:这应该是很基础的东西,不过笔者之前未接触过http编程,谨在此记录下学习的过程,可能不是最优解

方法:在服务器端部署html页面,并执行监听的Python代码,在客户端操作实现文件的上传与下载

1 [服务端] 创建本地文件夹用于开启http服务

首先开启power shell,在服务端本地创建一个文件夹用于开启http服务,例如创建了一个E:\WebServer文件夹,如图所示:

 进入power shell,输入命令:

cd E:\WebServer

输入开启http指令:

python -m http.server

出现如下情况,说明成功:

 此时,我们便可以在服务器的浏览器地址栏输入本机ip地址+端口号来访问http页面,例如:

http://172.1.1.1:8000

 至于本机ip地址,可以从右键“网络”,点击你的网络连接的蓝字,详细信息里面的ipv4地址进行查看,如图所示:

 此时,浏览器中的页面应该是这样:

看见这个页面,第一步就完成了!


2 [服务端] 编写监听脚本,用于客户端上传文件

在服务器端根文件夹下创建一个Python脚本(在别的地方创建应该也行,没试过):

from http.server import BaseHTTPRequestHandler, HTTPServer
import time


# 创建自定义的请求处理类
class FileUploadHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        start_time = time.time()
        content_length = int(self.headers['Content-Length'])
        # 读取客户端发送的二进制文件数据
        file_data = self.rfile.read(content_length)

        # 在这里可以对接收到的文件数据进行处理,例如保存到磁盘
        with open('uploaded_file.bin', 'wb') as file:
            file.write(file_data)

        self.send_response(200)
        self.end_headers()
        self.wfile.write(b'File uploaded successfully.')

        end_time = time.time()
        time_elapsed_ms = int((end_time - start_time) * 1000)
        print(f"Update in {time_elapsed_ms} ms")


# 启动服务器
def run_server():
    server_address = ('your web server', 8000)  # 可以根据需要修改端口号
    httpd = HTTPServer(server_address, FileUploadHandler)
    print('Server running on port 8000...')
    httpd.serve_forever()


# 运行服务器
run_server()

注意,在 ‘your web server’ 处输入自己的ip地址


3 [服务端] 编写html脚本,用于显示上传文件界面

<!DOCTYPE html>
<html>

<head>
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.6.0.js" type="text/javascript"></script>
    <!-- <script src="./jquery-3.6.0.js" type="text/javascript"></script> -->
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
</head>

<body>
    <form id="uploadForm" action="/upload" enctype="multipart/form-data" method="post" onsubmit="return submitFile()">
        <div><input type="file" name="file" multiple></div>
        <br>
        <div><input type="submit" value="upload"> </div>
    </form>
    <script>
        function submitFile() {
            // formData = new FormData($('#uploadForm')[0])
            files = $('#uploadForm')[0].file.files
            for (i = 0; i < files.length; i++) {
                $.ajax({
                    url: "/upload?fileName=" + encodeURIComponent(files[i].name),
                    type: "POST",
                    data: files[i],
                    success: function (data) {
                        console.info("success", data);
                    },
                    error: function (data) {
                        console.warn("fail", data);
                    },
                    processData: false,
                    contentType: "multipart/form-data",
                    // contentType: "application/octet-stream"
                });
            }
            return false;
        }
    </script>
</body>

</html>

上述代码参考了:python HTTPServer 实现文件上传下载_xiekch的博客-CSDN博客  

将上述代码写入到记事本文件,再保存成html文件,放入服务器根目录,并命名为index.html

http页面便会更改成既定样式,即此时再次打开http页面,应该呈现:


4 [客户端] 编写上传文件脚本

使用另一台电脑充当客户端,编写上传文件的Python脚本:

import requests
import os

# 指定服务器URL和要上传的文件路径
server_url = 'http://your web server:8000/upload'
file_path = '/your file path/file.bin'

testResponse = requests.get(server_url)
if testResponse.status_code == 200:
    print("与服务器的连接正常!")
else:
    print("无法连接到服务器!")

with open(file_path, 'rb') as file:
    file_data = file.read()

response = requests.post(server_url, files={'file': 'file'})

if response.status_code == 200:
    print("文件上传成功!")
else:
    print("文件上传失败!")

同样注意,在 ‘your web server’ 处输入自己的ip地址,在your file path写上文件路径

Windows系统下,文件路径可以使用双斜杠:

http://172.1.1.1:8000//data.bin

 MacOS系统下,目前测试可以使用如下格式:

'/users/north/desktop/data.bin'

5 [客户端] 编写下载文件脚本

同样的,使用另一个Python文件编写下载文件脚本:

import time
import requests

response = requests.get("http://your web server:8000//file.bin")
with open("data.bin", "wb") as f:
f.write(response.content)

再次,在 ‘your web server’ 处输入自己的ip地址


6 [客户端] 实现效果

上述步骤都准备充分后,运行 [服务端] 监听脚本,此时Python IDE的Terminal窗口应提示:

同时,脚本应处于一直运行状态(当前显示停止键则为正在持续运行),以持续监听:

 此时运行[客户端]的下载文件脚本,可将服务器中的目标文件进行下载,笔者又另行编写了一个记录下载时间的功能,出现下述结果说明下载成功,当然,也可以用类似于上传问价脚本的判断机制进行文件是否下载成功的判断

[客户端]进入服务器的http地址,选择本地文件进行上传:

同样的,[服务器]监听终端出现如下消息说明上传成功:

 [服务器]根目录会出现暂存文件,后续若需要进一步对该暂存文件进行处理则可以进一步修改脚本

230524修订:需要在运行服务端监听脚本前就在客户端进入上传文件页面,否则会产生Error,因暂不影响功能实现,目前尚未研究成因 


The End

物联沃分享整理
物联沃-IOTWORD物联网 » 使用Python http.server搭建文件下载/上传的HTTP服务器

发表评论