自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Python解析multipart boundary:aiohttp與requests文件上傳詳解

開發(fā) 前端
本文詳細介紹了multipart/form-data中boundary的作用,并對Python中requests與aiohttp兩種HTTP請求庫在處理boundary時的自動與手動構(gòu)造方式進行了深入解析。

目錄

1. 什么是boundary?

2. requests庫中boundary的處理

? 2.1 自動處理boundary

? 2.2 手動設(shè)置 boundary

? 2.3 手動構(gòu)建boundary

3. aiohttp庫中boundary的處理

        ? 3.1 自動處理boundary

        ? 3.2 手動設(shè)置 boundary

         ? 3.3 手動構(gòu)建boundary

 4. aiohttp與requests的優(yōu)缺點對比

 5. 總結(jié)

 6. 相關(guān)閱讀

1. 什么是boundary?

在HTTP協(xié)議中,當我們使用multipart/form-data提交表單時,整個請求體包含多個部分,每部分之間的邊界由一個稱為boundary的字符串分隔。例如,HTTP請求頭中可能包含如下內(nèi)容:

Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

這個boundary字符串保證服務器能夠正確解析各個字段和文件內(nèi)容,是構(gòu)造復雜表單數(shù)據(jù)的重要組成部分。

2. requests庫中boundary的處理

2.1 自動處理boundary

使用requests發(fā)送表單數(shù)據(jù)時,只需要將文件或字段通過files和data參數(shù)傳遞,requests會自動生成boundary并封裝數(shù)據(jù)。

import requests

# 目標URL(測試用:httpbin.org可返回提交的數(shù)據(jù))
url = 'http://httpbin.org/post'

# 構(gòu)造文件上傳數(shù)據(jù):requests會自動構(gòu)造multipart/form-data請求
files = {
    # 第一個參數(shù)為字段名稱,元組中依次為:(文件名, 文件對象, MIME類型)
    'file':('test.txt', open('test.txt', 'rb'), 'text/plain')
}

# 發(fā)送POST請求
response = requests.post(url, files=files)

# 打印服務器返回內(nèi)容
print(response.text)

注釋說明:

? 此示例中,requests自動在請求頭中生成Content-Type及其中的boundary,無需開發(fā)者手動干預。

? 適用于大部分常規(guī)使用場景。

2.2 手動設(shè)置 Boundary

在某些特殊情況下,可能需要手動指定 boundary。此時可以借助 requests-toolbelt 庫中的 MultipartEncoder。

首先需安裝 requests-toolbelt:

pip install requests-toolbelt

下面是手動指定 boundary 的示例代碼:

from requests_toolbelt.multipart.encoder import MultipartEncoder
import requests

def send_formdata_manual():
    url = 'http://httpbin.org/post'
    # 自定義 boundary 字符串
    boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'
    # 使用 MultipartEncoder 構(gòu)造 multipart 數(shù)據(jù),同時指定 boundary
    encoder = MultipartEncoder(
        fields={
            'field1': 'value1',
            'file': ('test.txt', open('test.txt', 'rb'), 'text/plain')
        },
        boundary=boundary
    )
    # 設(shè)置 Content-Type 頭,包含自定義的 boundary
    headers = {'Content-Type': encoder.content_type}
    # 發(fā)送 POST 請求
    response = requests.post(url, data=encoder, headers=headers)
    print("手動設(shè)置 boundary 的響應:", response.text)

send_formdata_manual()

2.3 手動構(gòu)建boundary

有時我們需要對請求體的格式進行更精細的控制,此時可以選擇手動構(gòu)建multipart/form-data格式的數(shù)據(jù)。

import requests

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

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

# 構(gòu)造請求體各部分數(shù)據(jù),注意各部分之間以boundary分隔
data_lines = []
# 添加第一個字段:普通文本字段
data_lines.append('--' + boundary)
data_lines.append('Content-Disposition: form-data; name="field1"')
data_lines.append('')  # 空行分隔頭與內(nèi)容
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('')
# 讀取文件內(nèi)容(確保當前目錄下有test.txt文件)
with open('test.txt', 'r', encoding='utf-8') as f:
    data_lines.append(f.read())

# 結(jié)束標志:加上結(jié)尾的boundary標記
data_lines.append('--' + boundary + '--')

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

# 構(gòu)造請求頭,指明Content-Type及boundary
headers = {
    'Content-Type': 'multipart/form-data; boundary=' + boundary
}

# 發(fā)送POST請求,此處需要將body轉(zhuǎn)換為字節(jié)串
response = requests.post(url, data=body.encode('utf-8'), headers=headers)
print(response.text)

注釋說明:

? 手動構(gòu)造的流程:先定義好boundary,再將每個部分的數(shù)據(jù)按照標準格式拼接(包括Content-Disposition和Content-Type等)。

? 最后將拼接好的字符串通過encode('utf-8')轉(zhuǎn)為字節(jié)發(fā)送。

3. aiohttp庫中boundary的處理

3.1 自動處理boundary

aiohttp作為異步HTTP庫,同樣支持通過aiohttp.FormData構(gòu)造multipart/form-data數(shù)據(jù),并自動管理boundary。

import aiohttp
import asyncio

async def main():
    url = 'http://httpbin.org/post'
    # 使用aiohttp提供的FormData構(gòu)造表單數(shù)據(jù)
    form = aiohttp.FormData()
    form.add_field('field1', 'value1')
    # 添加文件字段,注意以二進制方式打開文件
    form.add_field('file',
                   open('test.txt', 'rb'),
                   filename='test.txt',
                   content_type='text/plain')
    
    # 使用異步上下文管理器發(fā)送請求
    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,并構(gòu)造請求體。

? 異步寫法適合高并發(fā)或異步應用場景。

3.2 手動設(shè)置 Boundary

有時需要自定義 boundary,比如為了和服務端進行特殊交互,此時可以使用 aiohttp.MultipartWriter 手動構(gòu)造 multipart 數(shù)據(jù)。

import aiohttp
import asyncio

async def send_formdata_manual():
    # 自定義 boundary 字符串(注意確保不會與數(shù)據(jù)內(nèi)容沖突)
    boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'
    # 創(chuàng)建 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')
    
    # 發(fā)送 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("手動設(shè)置 boundary 的響應:", result)

# 運行異步任務
asyncio.run(send_formdata_manual())

代碼說明:

? 使用 aiohttp.MultipartWriter 手動構(gòu)造 multipart 數(shù)據(jù),并通過參數(shù) boundary 指定自定義分隔符。

? 每個字段使用 append 方法添加,并通過 set_content_disposition 設(shè)置字段名稱與文件信息。

? 通過 aiohttp 異步發(fā)送請求,觀察服務端對自定義 boundary 的處理結(jié)果。

3.3 手動構(gòu)建boundary

與requests類似,aiohttp也支持手動構(gòu)造請求體,適用于需要完全自定義請求體格式的場景。

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())
    
    # 結(jié)束標記
    parts.append('--' + boundary + '--')
    
    # 構(gòu)造完整請求體
    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())

注釋說明:

? 手動構(gòu)造流程與requests類似,需自行拼接各部分數(shù)據(jù)和boundary。

? 注意在異步環(huán)境中,通過await獲取響應數(shù)據(jù)。

4. aiohttp與requests的優(yōu)缺點對比

特性

requests

aiohttp

同步/異步

同步,適合簡單腳本及同步流程

異步,適合高并發(fā)、大規(guī)模請求場景

易用性

API設(shè)計直觀、簡單易用,自動處理multipart表單數(shù)據(jù)

API設(shè)計靈活,適合異步編程,但學習曲線稍陡

性能

在低并發(fā)場景下表現(xiàn)良好,但阻塞I/O可能導致性能瓶頸

利用異步機制高效處理并發(fā)請求,性能優(yōu)勢明顯

手動構(gòu)造支持

允許手動構(gòu)造請求體,適用于對請求數(shù)據(jù)精細控制的需求

同樣支持手動構(gòu)造,但通常建議使用內(nèi)置FormData自動處理

社區(qū)與文檔

社區(qū)成熟,文檔詳細,示例豐富

社區(qū)活躍,文檔逐步完善,但部分高級用法可能需要參考源碼

注釋說明:

? 如果項目對并發(fā)和性能有較高要求,aiohttp無疑是更好的選擇;

? 對于多數(shù)普通應用,requests的簡單易用更能提高開發(fā)效率。

5. 總結(jié)

本文詳細介紹了multipart/form-data中boundary的作用,并對Python中requests與aiohttp兩種HTTP請求庫在處理boundary時的自動與手動構(gòu)造方式進行了深入解析。通過完整的代碼示例,你可以看到兩者在實際應用中的實現(xiàn)細節(jié)及各自的優(yōu)缺點。無論是同步的requests還是異步的aiohttp,都能滿足大部分場景的需求,而如何選擇則應基于具體項目需求和性能要求。


責任編輯:武曉燕 來源: 不止于python
相關(guān)推薦

2009-07-16 17:26:11

WebWork文件上傳

2009-07-21 15:38:31

2009-11-24 15:01:59

PHP通用文件上傳類

2009-07-24 15:07:56

ASP.NET上傳文件

2024-01-23 09:02:35

PyYAML庫PythonYAML

2017-12-01 10:13:42

前端操作上傳

2009-08-03 17:22:15

JSON解析

2010-03-17 14:42:09

Python 文件

2012-06-13 02:02:43

ServletJavaJSP

2018-11-30 09:30:46

aiohttp爬蟲Python

2019-10-18 09:36:17

Oracle數(shù)據(jù)庫硬解析

2024-04-15 13:13:04

PythonJSON

2010-03-17 15:01:24

Python復制文件

2024-03-14 10:51:13

服務器技術(shù).NET Core

2010-09-16 15:17:33

2019-08-29 23:02:24

Python解析式表達列

2021-07-05 12:09:58

Python編程語言

2016-12-15 08:28:34

HttpURLConn上傳文件

2025-01-15 09:04:50

SPCXBar樣本均值

2010-04-22 13:56:21

Aix操作系統(tǒng)
點贊
收藏

51CTO技術(shù)棧公眾號