首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Python解析multipart boundary:aiohttp与requests文件上传详解

Python解析multipart boundary:aiohttp与requests文件上传详解

作者头像
不止于python
发布于 2025-03-17 08:20:23
发布于 2025-03-17 08:20:23
36200
代码可运行
举报
文章被收录于专栏:不止于python不止于python
运行总次数:0
代码可运行

简介

在Web开发中,处理文件上传或复杂表单数据时,经常需要使用multipart/form-data格式,而其中的boundary参数则是区分各部分数据的重要分隔符。本文将深入介绍boundary的概念,并针对Python中两个常用的HTTP请求库——aiohttprequests,分别展示自动与手动构建boundary的方式。最后,通过详细的对比,帮助你理解各自的优缺点,从而选择适合的解决方案。

1. 什么是boundary?

在HTTP协议中,当我们使用multipart/form-data提交表单时,整个请求体包含多个部分,每部分之间的边界由一个称为boundary的字符串分隔。例如,HTTP请求头中可能包含如下内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

这个boundary字符串保证服务器能够正确解析各个字段和文件内容,是构造复杂表单数据的重要组成部分。

2. requests库中boundary的处理

2.1 自动处理boundary

使用requests发送表单数据时,只需要将文件或字段通过filesdata参数传递,requests会自动生成boundary并封装数据。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import requests

# 目标URL(测试用:httpbin.org可返回提交的数据)
url = 'http://httpbin.org/post'

# 构造文件上传数据:requests会自动构造multipart/form-data请求
files = {
    # 第一个参数为字段名称,元组中依次为:(文件名, 文件对象, MIME类型)
    'file':('test.txt', open('test.txt', 'rb'), 'text/plain')
}

# 发送POST请求
response = requests.post(url, files=files)

# 打印服务器返回内容
print(response.text)

注释说明

  • • 此示例中,requests自动在请求头中生成Content-Type及其中的boundary,无需开发者手动干预。
  • • 适用于大部分常规使用场景。

2.2 手动设置 Boundary

在某些特殊情况下,可能需要手动指定 boundary。此时可以借助 requests-toolbelt 库中的 MultipartEncoder

首先需安装 requests-toolbelt:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
pip install requests-toolbelt

下面是手动指定 boundary 的示例代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from requests_toolbelt.multipart.encoder import MultipartEncoder
import requests

def send_formdata_manual():
    url = 'http://httpbin.org/post'
    # 自定义 boundary 字符串
    boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'
    # 使用 MultipartEncoder 构造 multipart 数据,同时指定 boundary
    encoder = MultipartEncoder(
        fields={
            'field1': 'value1',
            'file': ('test.txt', open('test.txt', 'rb'), 'text/plain')
        },
        boundary=boundary
    )
    # 设置 Content-Type 头,包含自定义的 boundary
    headers = {'Content-Type': encoder.content_type}
    # 发送 POST 请求
    response = requests.post(url, data=encoder, headers=headers)
    print("手动设置 boundary 的响应:", response.text)

send_formdata_manual()

2.3 手动构建boundary

有时我们需要对请求体的格式进行更精细的控制,此时可以选择手动构建multipart/form-data格式的数据。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import requests

# 目标URL
url = 'http://httpbin.org/post'

# 自定义boundary字符串
boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'

# 构造请求体各部分数据,注意各部分之间以boundary分隔
data_lines = []
# 添加第一个字段:普通文本字段
data_lines.append('--' + boundary)
data_lines.append('Content-Disposition: form-data; name="field1"')
data_lines.append('')  # 空行分隔头与内容
data_lines.append('value1')

# 添加第二个字段:文件字段
data_lines.append('--' + boundary)
data_lines.append('Content-Disposition: form-data; name="file"; filename="test.txt"')
data_lines.append('Content-Type: text/plain')
data_lines.append('')
# 读取文件内容(确保当前目录下有test.txt文件)
with open('test.txt', 'r', encoding='utf-8') as f:
    data_lines.append(f.read())

# 结束标志:加上结尾的boundary标记
data_lines.append('--' + boundary + '--')

# 将各部分用CRLF连接
body = '\r\n'.join(data_lines)

# 构造请求头,指明Content-Type及boundary
headers = {
    'Content-Type': 'multipart/form-data; boundary=' + boundary
}

# 发送POST请求,此处需要将body转换为字节串
response = requests.post(url, data=body.encode('utf-8'), headers=headers)
print(response.text)

注释说明

  • • 手动构造的流程:先定义好boundary,再将每个部分的数据按照标准格式拼接(包括Content-Disposition和Content-Type等)。
  • • 最后将拼接好的字符串通过encode('utf-8')转为字节发送。

3. aiohttp库中boundary的处理

3.1 自动处理boundary

aiohttp作为异步HTTP库,同样支持通过aiohttp.FormData构造multipart/form-data数据,并自动管理boundary。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import aiohttp
import asyncio

async def main():
    url = 'http://httpbin.org/post'
    # 使用aiohttp提供的FormData构造表单数据
    form = aiohttp.FormData()
    form.add_field('field1', 'value1')
    # 添加文件字段,注意以二进制方式打开文件
    form.add_field('file',
                   open('test.txt', 'rb'),
                   filename='test.txt',
                   content_type='text/plain')
    
    # 使用异步上下文管理器发送请求
    async with aiohttp.ClientSession() as session:
        async with session.post(url, data=form) as resp:
            print(await resp.text())

# 运行异步任务
asyncio.run(main())

注释说明

  • aiohttp.FormData会自动生成适合的boundary,并构造请求体。
  • • 异步写法适合高并发或异步应用场景。

3.2 手动设置 Boundary

有时需要自定义 boundary,比如为了和服务端进行特殊交互,此时可以使用 aiohttp.MultipartWriter 手动构造 multipart 数据。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import aiohttp
import asyncio

async def send_formdata_manual():
    # 自定义 boundary 字符串(注意确保不会与数据内容冲突)
    boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'
    # 创建 MultipartWriter 对象,手动指定 boundary
    mp_writer = aiohttp.MultipartWriter(boundary=boundary)
    
    # 添加普通字段
    part1 = mp_writer.append('value1')
    part1.set_content_disposition('form-data', name='field1')
    
    # 添加文件字段
    with open('test.txt', 'rb') as f:
        part2 = mp_writer.append(f.read(), {'Content-Type': 'text/plain'})
        part2.set_content_disposition('form-data', name='file', filename='test.txt')
    
    # 发送 POST 请求
    async with aiohttp.ClientSession() as session:
        async with session.post('http://httpbin.org/post', data=mp_writer) as resp:
            result = await resp.text()
            print("手动设置 boundary 的响应:", result)

# 运行异步任务
asyncio.run(send_formdata_manual())

代码说明:

  • • 使用 aiohttp.MultipartWriter 手动构造 multipart 数据,并通过参数 boundary 指定自定义分隔符。
  • • 每个字段使用 append 方法添加,并通过 set_content_disposition 设置字段名称与文件信息。
  • • 通过 aiohttp 异步发送请求,观察服务端对自定义 boundary 的处理结果。

3.3 手动构建boundary

与requests类似,aiohttp也支持手动构造请求体,适用于需要完全自定义请求体格式的场景。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import aiohttp
import asyncio

async def main():
    url = 'http://httpbin.org/post'
    
    # 自定义boundary
    boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'
    parts = []
    # 添加普通文本字段
    parts.append('--' + boundary)
    parts.append('Content-Disposition: form-data; name="field1"')
    parts.append('')
    parts.append('value1')
    
    # 添加文件字段
    parts.append('--' + boundary)
    parts.append('Content-Disposition: form-data; name="file"; filename="test.txt"')
    parts.append('Content-Type: text/plain')
    parts.append('')
    with open('test.txt', 'r', encoding='utf-8') as f:
        parts.append(f.read())
    
    # 结束标记
    parts.append('--' + boundary + '--')
    
    # 构造完整请求体
    body = '\r\n'.join(parts)
    headers = {
        'Content-Type': 'multipart/form-data; boundary=' + boundary
    }
    
    async with aiohttp.ClientSession() as session:
        async with session.post(url, data=body.encode('utf-8'), headers=headers) as resp:
            print(await resp.text())

asyncio.run(main())

注释说明

  • • 手动构造流程与requests类似,需自行拼接各部分数据和boundary。
  • • 注意在异步环境中,通过await获取响应数据。

4. aiohttp与requests的优缺点对比

特性

requests

aiohttp

同步/异步

同步,适合简单脚本及同步流程

异步,适合高并发、大规模请求场景

易用性

API设计直观、简单易用,自动处理multipart表单数据

API设计灵活,适合异步编程,但学习曲线稍陡

性能

在低并发场景下表现良好,但阻塞I/O可能导致性能瓶颈

利用异步机制高效处理并发请求,性能优势明显

手动构造支持

允许手动构造请求体,适用于对请求数据精细控制的需求

同样支持手动构造,但通常建议使用内置FormData自动处理

社区与文档

社区成熟,文档详细,示例丰富

社区活跃,文档逐步完善,但部分高级用法可能需要参考源码

注释说明

  • • 如果项目对并发和性能有较高要求,aiohttp无疑是更好的选择;
  • • 对于多数普通应用,requests的简单易用更能提高开发效率。

5. 总结

本文详细介绍了multipart/form-data中boundary的作用,并对Python中requests与aiohttp两种HTTP请求库在处理boundary时的自动与手动构造方式进行了深入解析。通过完整的代码示例,你可以看到两者在实际应用中的实现细节及各自的优缺点。无论是同步的requests还是异步的aiohttp,都能满足大部分场景的需求,而如何选择则应基于具体项目需求和性能要求。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-03-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
jq ajax文件上传(h5文件上传,后端接收异常,不小心传为字符串形式了)
重点就是这个设置:contentType: ‘multipart/form-data; boundary=—-WebKitFormBoundary7MA4YWxkTrZu0gW’,
超级小可爱
2023/10/15
3350
aiohttp 异步http请求-4.文件上传multipart/form-data
前言 文件上传接口,post 请求参数类型content-type:multipart/form-data,上传文件分2种情况 小文件上传,可以直接用open函数读取 大文件上传,aiohttp支持多种类型的文件以流媒体的形式上传 官方文档示例 上传 multipart 类型 url = 'http://httpbin.org/post' files = {'file': open('report.xls', 'rb')} await session.post(url, data=files) 也可以明确
上海-悠悠
2022/04/22
3.2K0
aiohttp 异步http请求-4.文件上传multipart/form-data
Python+Requests multipart/form-data实现图片、附件上传实例
r = requests.post(url, data, files=files)
王大力测试进阶之路
2019/10/25
9.9K0
Python+Requests multipart/form-data实现图片、附件上传实例
HTTP请求报文和响应报文
一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成。
10JQKA
2019/10/23
2.5K0
HTTP请求报文和响应报文
python接口自动化18-requests-toolbelt处理multipart/form-data
一、requests-toolbelt 1.官方文档地址:[requests-toolbelt官方文档](https://pypi.python.org/pypi/requests-toolbelt/) 2.环境安装 > pip install requests-toolbelt 二、multipart/form-data传文件 ``` from requests_toolbelt import MultipartEncoder import requests m = MultipartEncoder(
企鹅号小编
2018/03/02
4.2K0
python接口自动化18-requests-toolbelt处理multipart/form-data
熟悉POST提交数据的4种方式,接口测试更高效
Hi,大家好。我们都知道POST一般用于向服务端提交数据,POST提交数据的 4 种格式即Content-Type的4种形式,尤其注意每种格式中http发送请求时body中数据的格式。4种形式分别是:
可可的测试小栈
2021/12/10
2.2K0
熟悉POST提交数据的4种方式,接口测试更高效
Python 文件上传:如何使用 multipart/form-data 编码和 requests 包
在许多应用程序中,将文件上传到网站服务器是一个常见任务。然而,在 Python 中实现它可能很有挑战性。因为 Python 标准库没有提供创建 multipart/form-data 编码类型请求的内置方法。这种编码类型允许发送二进制数据和其他表单字段。
jackcode
2023/02/27
2.7K0
Python Request POST 上传文件 Multipart/form-data
最后在分享一个web开发的技术网站,详细的介绍了请求头的各种参数:web开发技术网站 手机app抓包工具推荐:小黄鸟(HTTPCanary)
EXI-小洲
2022/12/13
2.6K0
Python Request POST 上传文件 Multipart/form-data
python 基于aiohttp的异步爬虫实战
钢铁知识库,一个学习python爬虫、数据分析的知识库。人生苦短,快用python。
钢铁知识库
2022/09/19
1.1K0
揭秘前端文件上传原理(一)
在平时工作中,总是会接触过很多文件上传的功能,因为用惯了各种操作库来处理,所以总有一种云里雾里的感觉,没有清晰的思路,归根到底还是没有理解文件上传的原理。接下来将揭起工具库的面纱,看看文件上传到底是怎么一回事,深入了解文件上传的本质。
用户1462769
2019/09/09
12.6K0
揭秘前端文件上传原理(一)
Django学习笔记之Ajax与文件上传
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。
Jetpropelledsnake21
2018/08/10
1.8K0
Django学习笔记之Ajax与文件上传
POST请求和GET请求如何传递和接收解析参数
接口参数应该怎么传递是每个项目应该面对的问题,这跟编程语言无关,今天来总结一波常用的接口参数传递方式。
码农小胖哥
2020/10/10
27.5K0
POST请求和GET请求如何传递和接收解析参数
Android 网络请求原理以及原始数据包
关于 HTTP 请求报文和响应报文的格式这里就不再过多介绍了,简单说,HTTP 协议是以 ASCII 码传输,建立在 TCP/IP 协议之上的应用层规范。规范把 HTTP 请求分为三个部分:请求行、请求头、请求体。类似于:
开发者
2019/12/26
9630
Android 网络请求原理以及原始数据包
Python网络请求-aiohttp
在 Python 众多的 HTTP 客户端中,最有名的莫过于requests、aiohttp和httpx。
码客说
2021/11/29
1.4K0
CVE-2025-26319:FlowiseAI未授权任意文件写入漏洞
FlowiseAI 是一款开源的低代码/无代码工具,用于快速构建基于大语言模型(LLM)的应用程序。它通过可视化拖拽组件,让用户无需或仅需少量编码就能创建聊天机器人、文档问答等应用,并支持多种大语言模型和向量数据库的集成。其核心功能包括记忆与对话、API 嵌入等,可应用于工作流自动化和文档问答等场景。FlowiseAI 支持本地、Docker 和云平台部署,完全开源免费,适合开发者和非技术用户快速搭建 AI 应用。
Timeline Sec
2025/06/11
2230
CVE-2025-26319:FlowiseAI未授权任意文件写入漏洞
python接口自动化(十)--post请求四种传送正文方式(详解)
  post请求我在python接口自动化(八)--发送post请求的接口(详解)已经讲过一部分了,主要是发送一些较长的数据,还有就是数据比较安全等。我们要知道post请求四种传送正文方式首先需要先了解一下常见的四种编码方式:
北京-宏哥
2019/09/11
3.9K0
python接口自动化(十)--post请求四种传送正文方式(详解)
PHP 构造 multipart/form-data 格式 POST 请求体的方法
最近在尝试基于 PHP 做一个反向代理 HTTP 的程序,其中一个需求是将程序收到的HTTP请求还原回 RFC2616 的原始格式。
zgq354
2019/11/24
5.2K0
python requests post 使用 multipart/form-data 上传文件方法
使用 requests 的 post files 请求,发现服务端没法接受到文件,总提示请上传图片
卓越笔记
2023/03/11
3.4K0
python requests post 使用 multipart/form-data 上传文件方法
【详解】burpsuite上传截断及截断原理介绍
在Web安全测试中,文件上传功能是一个常见的攻击点。攻击者可以通过各种手段绕过服务器的文件类型和大小限制,上传恶意文件,从而执行任意代码或导致其他安全问题。Burp Suite 是一个广泛使用的Web应用安全测试工具,它提供了强大的功能来帮助安全测试人员进行文件上传截断测试。
大盘鸡拌面
2025/05/13
2850
Python Requests Post for 5 Styles
最常见的 POST 提交数据的方式了。浏览器的原生 form 表单,如果不设置 enctype属性,那么最终就会以 application/x-www-form-urlencoded方式提交数据。请求类似于下面这样:
happy123.me
2019/12/30
6530
推荐阅读
相关推荐
jq ajax文件上传(h5文件上传,后端接收异常,不小心传为字符串形式了)
更多 >
LV.0
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档