Python3实现通过HTTP协议进行文件上传及下载

2023-10-31

要实现这个功能,你需要在主机A上编写一个Python程序,该程序监听HTTP上传请求并处理上传的文件。同时,在主机B上,你可以使用任何支持HTTP POST请求的工具(如curl或浏览器插件)上传文件。

以下是一个简单的实现示例:

在主机A上的Python程序:

```python
from http.server import HTTPServer, BaseHTTPRequestHandler

class UploadHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers.get('Content-Length'))
        data = self.rfile.read(length)
        # 处理上传的文件,例如保存到本地
        print('Received file data:', data)

if __name__ == '__main__':
    # 指定监听的IP和端口
    server_address = ('', 8000)
    httpd = HTTPServer(server_address, UploadHandler)
    print('Server started at {}:{}'.format(*server_address))
    # 开始监听HTTP请求
    httpd.serve_forever()
```

在主机B上使用curl上传文件:

```
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @/path/to/file http://<主机A的IP>:8000/upload
```

其中,`/path/to/file`是要上传的文件的本地路径,`<主机A的IP>`是主机A的IP地址。

你也可以使用其他HTTP客户端工具或浏览器插件上传文件,只需设置正确的请求头和请求体即可。


我们可以在主机A的Python程序中添加保存文件的逻辑,例如将上传的文件保存到本地磁盘上。

以下是修改后的代码示例:

```python
import os
from http.server import HTTPServer, BaseHTTPRequestHandler

UPLOAD_DIR = '/path/to/upload/directory'  # 上传文件保存的目录

class UploadHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        # 读取上传的文件数据
        content_length = int(self.headers['Content-Length'])
        file_data = self.rfile.read(content_length)
        # 从请求头中获取文件名
        filename = self.headers.get('Filename', 'unknown')
        # 保存文件到本地
        filepath = os.path.join(UPLOAD_DIR, filename)
        with open(filepath, 'wb') as f:
            f.write(file_data)
        print('Saved file to', filepath)
        # 发送响应
        self.send_response(200)
        self.end_headers()

if __name__ == '__main__':
    # 创建上传目录
    os.makedirs(UPLOAD_DIR, exist_ok=True)
    # 指定监听的IP和端口
    server_address = ('', 8000)
    httpd = HTTPServer(server_address, UploadHandler)
    print('Server started at {}:{}'.format(*server_address))
    # 开始监听HTTP请求
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        pass
    httpd.server_close()
```

在上面的代码中,我们在`do_POST`方法中添加了保存文件的逻辑。上传的文件数据存储在`self.rfile`属性中,文件名存储在请求头的`Filename`字段中。我们将上传的文件保存到`UPLOAD_DIR`目录中,并打印保存的文件路径。

你需要将`/path/to/upload/directory`替换为实际的上传目录路径。如果目录不存在,程序会自动创建它。当然,你也可以使用其他的保存文件方法,例如将上传的文件保存到数据库中。

上述代码中的HTTP服务器将一直保持运行状态,因此可以将其作为一个守护进程在主机A上运行。你可以使用`nohup`和`&`将其放入后台运行,并将输出重定向到文件中,例如:

```
nohup python3 upload_server.py > upload_server.log 2>&1 &
```

这将把服务器进程放入后台运行,并将输出保存到名为`upload_server.log`的文件中。如果需要停止服务器进程,可以使用`kill`命令将其杀死。


在上面的示例中,上传文件的URL是根据HTTP请求的路径自动生成的。如果你需要自定义上传文件的URL,可以在主机A的Python程序中使用`path`参数来指定URL路径。以下是修改后的代码示例:

```python
import os
from http.server import HTTPServer, BaseHTTPRequestHandler

UPLOAD_DIR = '/path/to/upload/directory'  # 上传文件保存的目录

class UploadHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        # 读取上传的文件数据
        content_length = int(self.headers['Content-Length'])
        file_data = self.rfile.read(content_length)
        # 获取上传的文件名
        filename = os.path.basename(self.path)
        # 保存文件到本地
        filepath = os.path.join(UPLOAD_DIR, filename)
        with open(filepath, 'wb') as f:
            f.write(file_data)
        print('Saved file to', filepath)
        # 发送响应
        self.send_response(200)
        self.end_headers()

if __name__ == '__main__':
    # 创建上传目录
    os.makedirs(UPLOAD_DIR, exist_ok=True)
    # 指定监听的IP和端口
    server_address = ('', 8000)
    # 指定上传文件的URL路径
    upload_uri = '/upload'
    httpd = HTTPServer(server_address, UploadHandler)
    httpd.upload_uri = upload_uri
    print('Server started at {}:{}{}'.format(*server_address, upload_uri))
    # 开始监听HTTP请求
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        pass
    httpd.server_close()
```

在上面的代码中,我们使用`httpd.upload_uri`属性来存储上传文件的URL路径,并在启动服务器时将其打印出来。如果需要修改上传文件的URL路径,只需要修改`upload_uri`的值即可。

当客户端上传文件时,需要将文件上传到指定的URL路径,例如`http://host:port/upload`。你可以在客户端的代码中使用相同的URL路径来上传文件。


curl -X POST -H "Content-Type: application/octet-stream" --data-binary @nchome.tar.gz  http://10.168.1.197:8081

在重写`http.server.BaseHTTPRequestHandler`类中的`do_GET()`方法时,您可以使用以下函数来代表响应:

- `self.send_response()`:设置HTTP响应状态码。例如,`self.send_response(200)`表示返回一个状态码为200的HTTP响应。
- `self.send_header()`:设置HTTP响应头。例如,`self.send_header('Content-type', 'text/html')`表示设置HTTP响应头`Content-type`为`text/html`。
- `self.end_headers()`:结束HTTP响应头的设置。
- `self.wfile.write()`:将HTTP响应正文写入响应体中。例如,`self.wfile.write(b'Hello, World!')`表示将`Hello, World!`写入响应体中。

请注意,您必须以正确的顺序使用这些函数来构建完整的HTTP响应。首先,您必须使用`self.send_response()`设置HTTP响应状态码。然后,您可以使用`self.send_header()`设置HTTP响应头,然后使用`self.end_headers()`结束HTTP响应头的设置。最后,您可以使用`self.wfile.write()`将HTTP响应正文写入响应体中。

例如,以下是一个简单的示例,它从HTTP GET请求中获取请求路径和参数,并使用`self.wfile.write()`将响应正文写入响应体中:

```python
from http.server import BaseHTTPRequestHandler, HTTPServer

class MyHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        # 获取请求路径和参数
        path = self.path
        params = self.headers.get('Content-Length')
        
        # 构建HTTP响应
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(b'Hello, World!')

# 启动HTTP服务器
host = ''
port = 8000
httpd = HTTPServer((host, port), MyHTTPRequestHandler)
print(f'Starting server on {host}:{port}')
httpd.serve_forever()
```

在上面的示例中,`self.send_response(200)`设置HTTP响应状态码为200,`self.send_header('Content-type', 'text/html')`设置HTTP响应头`Content-type`为`text/html`,`self.end_headers()`结束HTTP响应头的设置,`self.wfile.write(b'Hello, World!')`将`Hello, World!`写入响应体中。


exit_code = result.returncode
# 检查脚本的结束码是否为0
if exit_code == 0:
print("脚本执行成功!")
else:
print("脚本执行失败,错误码为:", exit_code)
self.send_error(500)

 
 
在Python的http.server模块中,您可以使用BaseHTTPRequestHandler类来处理HTTP请求和响应。要将请求路径转换为视图函数,您需要覆盖BaseHTTPRequestHandler类中的do_GET方法,并在其中添加自定义路由逻辑。

以下是一个示例代码,其中基于不同的URL路径调用不同的视图函数:

```python
from http.server import HTTPServer, BaseHTTPRequestHandler

class MyHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.send_response(200)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            self.wfile.write(b'Hello World!')
        elif self.path == '/download':
            self.handle_download()
        else:
            self.handle_404()

    def handle_download(self):
        # logic to download a file
        self.send_response(200)
        self.send_header('Content-type', 'application/octet-stream')
        self.send_header('Content-Disposition', 'attachment; filename="example.txt"')
        self.end_headers()
        file_content = b'This is an example file.'
        self.wfile.write(file_content)

    def handle_404(self):
        self.send_error(404)

if __name__ == '__main__':
    server_address = ('', 8000)
    httpd = HTTPServer(server_address, MyHTTPRequestHandler)
    httpd.serve_forever()
```

在此示例中,我们覆盖了BaseHTTPRequestHandler类的do_GET方法,并根据请求的URL路径调用不同的方法。例如,当请求的路径为/时,我们将发送一个Hello World!消息。当请求的路径为/download时,我们将调用handle_download方法来下载一个文件。当请求的路径不是/或/download时,我们将调用handle_404方法来发送404错误响应。

您可以根据需要添加其他路由逻辑,并在相应的处理方法中添加自定义逻辑来生成响应内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python3实现通过HTTP协议进行文件上传及下载 的相关文章

随机推荐

  • FFmpeg安装与使用+Java API/SpringBoot项目使用

    目录 下载安装 介绍与简单使用 在项目中的使用 配置文件 工具类 使用 下载安装 Download FFmpeg 解压到指定文件夹 介绍与简单使用 FFmpeg是一个开源的跨平台视频和音频处理工具 可以处理各种格式的音视频文件 FFmpeg
  • echarts实现人物树形关系图实例

    写这个栗子的时候主要因为是刚刚做一个项目 要用到人物关系图 所以一直在找合适插件 最后选择echarts2 0的tree图最合适这个关系图了 哈哈 话不多少 现在就把效果图献上吧 ps 照片是网上下载的 莫要见外啊 这个使用的是echart
  • 引入并使用Element

    引入并使用Element 开发工具与关键技术 MVC 作者 汤池 撰写时间 2022 4 7 1 首先需要打开DW软件 新建一个html网页 然后保存到一个文件夹当中 2 然后打开element官网 下载使用Element必须引用的脚本文件
  • 2022/1/22记录网页

    65条消息 102 bert词向量进行文本分类和命名实体识别 u012416045的博客 CSDN博客 bert文本识别https blog csdn net u012416045 article details 88373965 Bert
  • 记一次kafka无法生产发送消息排查经历

    参考 欢迎点击原文 https stackoverflow com questions 37902167 kafka error while fetching metadata with correlation id leader not
  • c语言中简单变量必须,C语言规定,简单变量做实参时,它和对应形参之间的数据传递方式是()。 (A)地址传递 (B)单向值传递 (C)由...

    参考答案如下 语言规应形C由一般来说 各种调查报告在结构上都可分成哪几个部分 定地址B单演示PPT的结尾部分一般建议展示以下内容 通过startService再次启动Service时 简单间不会再执行onCreate 函数 变量蛋白质分子的
  • 图机器学习课程笔记7

    维生素C吃多了会上火 个人CSDN博文目录 cs224w 图机器学习 2021冬季课程学习笔记集合 目录 思维大纲 中文笔记 思维大纲 中文笔记
  • 树莓派入门教程 - 0 - 准备篇 - 0.3 树莓派串口访问终端

    电脑需要提前安装的工具 SSH 串口 终端神器 MobaXterm 官网下载链接 https mobaxterm mobatek net download html 使用到的硬件 USB转TTL模块 CH340 和 CP2102均可 CP2
  • 1.2-知识图谱有什么用?

    知识图谱经过几年的发展已经得到广泛的应用 当知识图谱遇上人工智能 更加突显出了它的优势和价值 最先应用于搜索 最典型的就是在谷歌搜索引擎里面应用 谷歌是在2012年率先提出来知识图谱的概念 提出这个概念的最主要的目的就是用于改善它的搜索引擎
  • ospf小结

    ospf卡住的原因 route id相同 认证不通过 区域ID不同 特殊区域标示不一致 优先级都为0 无法选举 MTU值不匹配 包的交互不完整 网络中丢包等 LSA加载不完全 hello包时间不一致 MA网络掩码不一致 虚链路建邻ABR的两
  • JVM常量池最全详解-常量池/运行时常量池/字符串常量池/基本类型常量池,看这一篇就够了

    JVM常量池最全详解 常量池 运行时常量池 字符串常量池 基本类型常量池 看这一篇就够了 常量池详解 1 字面量和符号引用 1 1 字面量 1 2 符号引用 2 常量池vs运行时常量池 3 常量池 静态常量池 4 运行时常量池 5 字符串常
  • Introduction to Scientific Programing and Simulation Using R chapter 04 答案

    strong span style font size 32px Ex1 span strong span style color 33cc00 programe cha4 6 ex1 img src https img blog csdn
  • h-a-p-p-e-n-before原则的理解

    happen before 可真是一个经典又老生常谈的话题 规则一共就八条 但看起来总有种抓不住重点的感觉 今天再整理一下对这八条规则的理解 首先我的理解是 happen before 的语义与在什么什么之前发生完全没有关系 其语义是如果
  • 网络安全实验室 综合关 解析

    网站地址 http hackinglab cn ShowQues php type pentest 第一关 渗透测试第一期 先看看 登录界面 发现可以注册和忘记密码 忘记密码可以重置密码 思路如下 重置admin密码 发现 不能直接重置密码
  • 【赠书活动|第四期《互联网广告系统:架构、算法与智能化》】

    文章目录 内容简介 作者简介 读者对象 大咖推荐 抽奖方式 本期中奖者 广告平台的建设和完善是一项长期工程 例如 谷歌早于2003年通过收购Applied Semantics开展Google AdSense 项目 而直到20年后的今天 谷歌
  • sql连接查询

    sql连接查询 单表查询 student表 select 列名 from 表名 查看全表 SELECT FROM student 可以匹配为全选 在student表中查找赵六的信息 SELECT FROM student WHERE sna
  • 插入时出现MyBatisSystemException: nested exception is

    检查完xml文件没错后 还是出现错误 org mybatis spring MyBatisSystemException nested exception is org apache ibatis binding BindingExcept
  • SourceInsight4.0黑色背景主题

    SourceInsight4 0黑色背景主题 在网上找了一通花了好多积分最后发现只改了代码区 左右代码索引文件列表和函数调用关系图都还是白底 最后自己在设置里面找了找 发现在这个版本中SI已经内置了一些常用的主题配色 先放效果图 设置在这里
  • JAVA设计模式(21) —装饰(Decorator)模式

    定义 动态的给一个对象添加一些额外的职责 就增加功能来说 Decorator模式相比生成子类更为灵活 类型 对象结构型模式 别名 包装模式 Wrapper 类图 Decorator装饰模式是一种结构型模式 它主要是解决 过度地使用了继承来扩
  • Python3实现通过HTTP协议进行文件上传及下载

    要实现这个功能 你需要在主机A上编写一个Python程序 该程序监听HTTP上传请求并处理上传的文件 同时 在主机B上 你可以使用任何支持HTTP POST请求的工具 如curl或浏览器插件 上传文件 以下是一个简单的实现示例 在主机A上的