0
# Multipart Processing
1
2
Streaming multipart/form-data encoding and decoding capabilities for efficient handling of file uploads, form submissions, and multipart responses. The implementation supports large files without loading everything into memory and provides progress monitoring.
3
4
## Capabilities
5
6
### Multipart Encoding
7
8
Creates streaming multipart/form-data content for HTTP requests with support for files, strings, and mixed content types.
9
10
```python { .api }
11
class MultipartEncoder:
12
"""
13
Generic interface for creating multipart/form-data request bodies.
14
15
Parameters:
16
- fields: dict or list of tuples containing form fields
17
- boundary: str, custom boundary string (auto-generated if None)
18
- encoding: str, character encoding (default: 'utf-8')
19
"""
20
def __init__(self, fields, boundary=None, encoding='utf-8'): ...
21
22
# Instance attributes
23
boundary_value: str # The raw boundary string
24
boundary: str # Formatted boundary with --
25
encoding: str # Character encoding
26
fields: any # Original fields provided
27
finished: bool # Whether encoding is complete
28
parts: list # Pre-computed parts
29
30
@property
31
def content_type(self) -> str:
32
"""Returns the Content-Type header value including boundary."""
33
34
@property
35
def len(self) -> int:
36
"""Returns the total length of the multipart content."""
37
38
def read(self, size: int = -1) -> bytes:
39
"""
40
Read and return up to size bytes of multipart data.
41
42
Parameters:
43
- size: int, number of bytes to read (-1 for all)
44
45
Returns:
46
bytes: multipart data chunk
47
"""
48
49
def to_string(self) -> bytes:
50
"""
51
Returns the entire multipart content as bytes.
52
53
Returns:
54
bytes: complete multipart data
55
"""
56
57
def __repr__(self) -> str:
58
"""Return string representation of the encoder."""
59
```
60
61
#### Usage Examples
62
63
```python
64
import requests
65
from requests_toolbelt import MultipartEncoder
66
67
# Simple form fields
68
encoder = MultipartEncoder({
69
'username': 'john_doe',
70
'email': 'john@example.com'
71
})
72
73
response = requests.post(
74
'https://httpbin.org/post',
75
data=encoder,
76
headers={'Content-Type': encoder.content_type}
77
)
78
79
# File upload with additional fields
80
encoder = MultipartEncoder({
81
'field': 'value',
82
'file': ('filename.txt', open('file.txt', 'rb'), 'text/plain'),
83
'another_file': ('data.json', open('data.json', 'rb'), 'application/json')
84
})
85
86
response = requests.post(
87
'https://httpbin.org/post',
88
data=encoder,
89
headers={'Content-Type': encoder.content_type}
90
)
91
92
# Streaming large file upload
93
with open('large_file.zip', 'rb') as f:
94
encoder = MultipartEncoder({
95
'file': ('large_file.zip', f, 'application/zip'),
96
'description': 'Large file upload'
97
})
98
99
response = requests.post(
100
'https://httpbin.org/post',
101
data=encoder,
102
headers={'Content-Type': encoder.content_type}
103
)
104
```
105
106
### Progress Monitoring
107
108
Monitor the progress of multipart uploads with callback functions.
109
110
```python { .api }
111
class MultipartEncoderMonitor:
112
"""
113
Monitor for tracking multipart upload progress.
114
115
Parameters:
116
- encoder: MultipartEncoder instance to monitor
117
- callback: function called with monitor instance on each read (optional)
118
"""
119
def __init__(self, encoder, callback=None): ...
120
121
# Instance attributes
122
encoder: MultipartEncoder # The wrapped encoder
123
callback: callable # Progress callback function
124
bytes_read: int # Number of bytes read so far
125
len: int # Total length of the multipart content
126
content_type: str # Delegates to encoder.content_type
127
128
@classmethod
129
def from_fields(cls, fields, boundary=None, encoding='utf-8', callback=None):
130
"""
131
Create a monitor from fields directly.
132
133
Parameters:
134
- fields: dict or list of tuples containing form fields
135
- boundary: str, custom boundary string (optional)
136
- encoding: str, character encoding (default: 'utf-8')
137
- callback: function called with monitor instance on each read (optional)
138
139
Returns:
140
MultipartEncoderMonitor: configured monitor instance
141
"""
142
143
def read(self, size: int = -1) -> bytes:
144
"""
145
Read data and trigger progress callback.
146
147
Parameters:
148
- size: int, number of bytes to read
149
150
Returns:
151
bytes: data chunk
152
"""
153
154
def to_string(self) -> bytes:
155
"""Returns the entire multipart content as bytes."""
156
157
def IDENTITY(monitor):
158
"""Default callback function that returns monitor unchanged."""
159
```
160
161
#### Usage Examples
162
163
```python
164
import requests
165
from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor
166
167
def progress_callback(monitor):
168
percent = (monitor.bytes_read / monitor.len) * 100
169
print(f"Upload progress: {percent:.1f}%")
170
171
encoder = MultipartEncoder({
172
'file': ('large_file.zip', open('large_file.zip', 'rb'), 'application/zip')
173
})
174
175
monitor = MultipartEncoderMonitor(encoder, progress_callback)
176
177
response = requests.post(
178
'https://httpbin.org/post',
179
data=monitor,
180
headers={'Content-Type': monitor.content_type}
181
)
182
```
183
184
### Multipart Decoding
185
186
Parse multipart responses into individual parts with headers and content.
187
188
```python { .api }
189
class MultipartDecoder:
190
"""
191
Decoder for multipart HTTP responses.
192
193
Parameters:
194
- content: bytes, the multipart response body
195
- content_type: str, the Content-Type header value
196
- encoding: str, character encoding (default: 'utf-8')
197
"""
198
def __init__(self, content, content_type, encoding='utf-8'): ...
199
200
# Instance attributes
201
content_type: str # Original Content-Type header
202
encoding: str # Response body encoding
203
boundary: bytes # Extracted boundary
204
205
@property
206
def parts(self) -> tuple:
207
"""Returns tuple of BodyPart objects."""
208
209
@classmethod
210
def from_response(cls, response, encoding='utf-8'):
211
"""
212
Create decoder from HTTP response.
213
214
Parameters:
215
- response: requests.Response object
216
- encoding: str, character encoding (default: 'utf-8')
217
218
Returns:
219
MultipartDecoder: configured decoder instance
220
"""
221
222
class BodyPart:
223
"""
224
Individual part of a multipart response.
225
226
Parameters:
227
- content: bytes, raw part content including headers
228
- encoding: str, character encoding
229
"""
230
def __init__(self, content, encoding): ...
231
232
# Instance attributes
233
encoding: str # Character encoding
234
content: bytes # Raw content (attribute, not property)
235
headers: CaseInsensitiveDict # Part headers
236
237
@property
238
def text(self) -> str:
239
"""Returns the part content as decoded text."""
240
```
241
242
#### Usage Examples
243
244
```python
245
import requests
246
from requests_toolbelt.multipart import MultipartDecoder
247
248
response = requests.get('https://example.com/multipart-response')
249
250
if 'multipart' in response.headers.get('Content-Type', ''):
251
decoder = MultipartDecoder(response.content, response.headers['Content-Type'])
252
253
for part in decoder.parts:
254
print(f"Headers: {part.headers}")
255
print(f"Content: {part.content}")
256
257
# Access as text if it's textual content
258
if 'text' in part.headers.get('Content-Type', ''):
259
print(f"Text: {part.text}")
260
```
261
262
### File Streaming from URLs
263
264
Stream files directly from URLs without downloading them first.
265
266
```python { .api }
267
class FileFromURLWrapper:
268
"""
269
File from URL wrapper for streaming files from remote URLs.
270
271
Provides stateless solution for streaming files from one server to another
272
without downloading the entire file into memory first.
273
274
Parameters:
275
- file_url: str, URL of the file to stream
276
- session: requests.Session, optional session for requests (default: new session)
277
278
Raises:
279
- FileNotSupportedError: If URL doesn't provide content-length header
280
"""
281
def __init__(self, file_url: str, session=None): ...
282
283
# Instance attributes
284
session: requests.Session # Session used for requests
285
len: int # Remaining bytes to read
286
raw_data: any # Raw response data stream
287
288
def read(self, chunk_size: int) -> bytes:
289
"""
290
Read file in chunks.
291
292
Parameters:
293
- chunk_size: int, number of bytes to read
294
295
Returns:
296
bytes: file data chunk
297
"""
298
```
299
300
#### Usage Examples
301
302
```python
303
import requests
304
from requests_toolbelt.multipart.encoder import FileFromURLWrapper
305
from requests_toolbelt import MultipartEncoder
306
307
# Stream file from URL without session
308
url = 'https://httpbin.org/image/png'
309
streaming_encoder = MultipartEncoder({
310
'file': FileFromURLWrapper(url),
311
'description': 'Image from URL'
312
})
313
314
response = requests.post(
315
'https://httpbin.org/post',
316
data=streaming_encoder,
317
headers={'Content-Type': streaming_encoder.content_type}
318
)
319
320
# Stream file with session
321
session = requests.Session()
322
streaming_encoder = MultipartEncoder({
323
'file': FileFromURLWrapper(url, session=session)
324
})
325
326
response = session.post(
327
'https://httpbin.org/post',
328
data=streaming_encoder,
329
headers={'Content-Type': streaming_encoder.content_type}
330
)
331
```
332
333
### Exceptions
334
335
```python { .api }
336
class ImproperBodyPartContentException(Exception):
337
"""Raised when body part content is malformed."""
338
339
class NonMultipartContentTypeException(Exception):
340
"""Raised when content type is not multipart."""
341
342
class FileNotSupportedError(Exception):
343
"""Raised when file from URL is not supported (missing content-length)."""
344
```