0
# File Upload Operations
1
2
Synchronous and asynchronous file upload capabilities with chunked transfer, progress tracking, and error recovery. TusPy provides both sync and async uploaders built on a common base class.
3
4
## Capabilities
5
6
### Base Uploader
7
8
Common functionality shared by synchronous and asynchronous uploaders.
9
10
```python { .api }
11
class BaseUploader:
12
"""
13
Object to control upload related functions.
14
15
Attributes:
16
file_path (str): Path to file for upload
17
file_stream (IO): Alternative file stream for upload
18
url (str): Upload URL if known (for resuming)
19
client (TusClient): Client instance for server communication
20
chunk_size (int): Size of chunks in bytes (default: sys.maxsize)
21
metadata (dict): Upload metadata dictionary
22
metadata_encoding (str): Encoding for metadata values (default: 'utf-8')
23
offset (int): Current upload position
24
stop_at (int): Offset to stop upload at
25
retries (int): Number of retry attempts on failure (default: 0)
26
retry_delay (int): Delay between retries in seconds (default: 30)
27
verify_tls_cert (bool): Whether to verify TLS certificates (default: True)
28
store_url (bool): Whether to store URL for resumability (default: False)
29
url_storage (Storage): Storage implementation for URL persistence
30
fingerprinter (Fingerprint): Fingerprint implementation for file identification
31
upload_checksum (bool): Whether to include upload checksums (default: False)
32
"""
33
34
DEFAULT_HEADERS = {"Tus-Resumable": "1.0.0"}
35
DEFAULT_CHUNK_SIZE = sys.maxsize
36
CHECKSUM_ALGORITHM_PAIR = ("sha1", hashlib.sha1)
37
38
def __init__(self, file_path: Optional[str] = None, file_stream: Optional[IO] = None,
39
url: Optional[str] = None, client: Optional[TusClient] = None,
40
chunk_size: int = sys.maxsize, metadata: Optional[Dict] = None,
41
metadata_encoding: Optional[str] = "utf-8", retries: int = 0,
42
retry_delay: int = 30, verify_tls_cert: bool = True,
43
store_url: bool = False, url_storage: Optional[Storage] = None,
44
fingerprinter: Optional[Fingerprint] = None, upload_checksum: bool = False):
45
"""
46
Initialize BaseUploader.
47
48
Parameters:
49
- file_path (Optional[str]): Path to file for upload
50
- file_stream (Optional[IO]): File stream alternative to file_path
51
- url (Optional[str]): Known upload URL for resuming
52
- client (Optional[TusClient]): Client instance for server communication
53
- chunk_size (int): Chunk size in bytes for uploads
54
- metadata (Optional[Dict]): Upload metadata dictionary
55
- metadata_encoding (Optional[str]): Encoding for metadata values
56
- retries (int): Number of retry attempts on failure
57
- retry_delay (int): Delay between retries in seconds
58
- verify_tls_cert (bool): Whether to verify TLS certificates
59
- store_url (bool): Whether to store URL for resumability
60
- url_storage (Optional[Storage]): Storage for URL persistence
61
- fingerprinter (Optional[Fingerprint]): File fingerprinting implementation
62
- upload_checksum (bool): Whether to include upload checksums
63
"""
64
```
65
66
### Header Management
67
68
Methods for managing HTTP headers in uploads.
69
70
```python { .api }
71
def get_headers(self) -> Dict[str, str]:
72
"""
73
Return headers of the uploader instance including client headers.
74
75
Returns:
76
Dict[str, str]: Combined headers from uploader and client
77
"""
78
79
def get_url_creation_headers(self) -> Dict[str, str]:
80
"""
81
Return headers required to create upload url.
82
83
Returns:
84
Dict[str, str]: Headers for POST request to create upload URL
85
"""
86
```
87
88
### File Operations
89
90
Methods for working with files and file streams.
91
92
```python { .api }
93
def get_file_stream(self) -> IO:
94
"""
95
Return a file stream instance of the upload.
96
97
Returns:
98
IO: File stream positioned at start of file
99
"""
100
101
def get_file_size(self) -> int:
102
"""
103
Return size of the file in bytes.
104
105
Returns:
106
int: File size in bytes
107
"""
108
109
def get_request_length(self) -> int:
110
"""
111
Return length of next chunk upload in bytes.
112
113
Returns:
114
int: Length of next chunk to upload
115
"""
116
```
117
118
### URL and Offset Management
119
120
Methods for managing upload URLs and tracking progress.
121
122
```python { .api }
123
def set_url(self, url: str):
124
"""
125
Set the upload URL and optionally store it.
126
127
Parameters:
128
- url (str): Upload URL from server
129
"""
130
131
def get_offset(self) -> int:
132
"""
133
Return current offset from tus server.
134
135
Makes HTTP HEAD request to retrieve current upload position.
136
137
Returns:
138
int: Current upload offset in bytes
139
"""
140
```
141
142
### Metadata Handling
143
144
Methods for encoding and managing upload metadata.
145
146
```python { .api }
147
def encode_metadata(self) -> List[str]:
148
"""
149
Return list of encoded metadata as defined by the Tus protocol.
150
151
Returns:
152
List[str]: Encoded metadata strings for upload-metadata header
153
"""
154
```
155
156
### Properties
157
158
Read-only properties for accessing uploader state and configuration.
159
160
```python { .api }
161
@property
162
def checksum_algorithm(self) -> Callable:
163
"""
164
Return checksum algorithm function for upload verification.
165
166
Returns:
167
Callable: Checksum algorithm function (default: hashlib.sha1)
168
"""
169
170
@property
171
def checksum_algorithm_name(self) -> str:
172
"""
173
Return name of checksum algorithm for upload verification.
174
175
Returns:
176
str: Algorithm name (default: "sha1")
177
"""
178
179
@property
180
def client_cert(self) -> Optional[Union[str, Tuple[str, str]]]:
181
"""
182
Return client certificate configuration from associated client.
183
184
Returns:
185
Optional[Union[str, Tuple[str, str]]]: Client certificate path(s) or None
186
"""
187
```
188
189
### Synchronous Uploader
190
191
Synchronous file uploader using the requests library.
192
193
```python { .api }
194
class Uploader(BaseUploader):
195
"""Synchronous file uploader using requests library."""
196
197
def upload(self, stop_at: Optional[int] = None):
198
"""
199
Perform file upload.
200
201
Performs continuous upload of chunks of the file. The size uploaded at each
202
cycle is the value of the attribute 'chunk_size'.
203
204
Parameters:
205
- stop_at (Optional[int]): Offset value where upload should stop.
206
Defaults to file size if not specified.
207
"""
208
209
def upload_chunk(self):
210
"""
211
Upload single chunk of file.
212
213
Uploads one chunk starting from current offset and updates offset
214
with server response.
215
"""
216
217
def create_url(self) -> str:
218
"""
219
Return new upload url from server.
220
221
Makes POST request to tus server to create a new upload url for the file.
222
223
Returns:
224
str: Upload URL for this file
225
226
Raises:
227
TusCommunicationError: If server returns error or no location header
228
"""
229
```
230
231
### Asynchronous Uploader
232
233
Asynchronous file uploader using the aiohttp library.
234
235
```python { .api }
236
class AsyncUploader(BaseUploader):
237
"""Asynchronous file uploader using aiohttp library."""
238
239
async def upload(self, stop_at: Optional[int] = None):
240
"""
241
Perform file upload asynchronously.
242
243
Performs continuous upload of chunks of the file. The size uploaded at each
244
cycle is the value of the attribute 'chunk_size'.
245
246
Parameters:
247
- stop_at (Optional[int]): Offset value where upload should stop.
248
Defaults to file size if not specified.
249
"""
250
251
async def upload_chunk(self):
252
"""
253
Upload single chunk of file asynchronously.
254
255
Uploads one chunk starting from current offset and updates offset
256
with server response.
257
"""
258
259
async def create_url(self) -> str:
260
"""
261
Return new upload url from server asynchronously.
262
263
Makes async POST request to tus server to create a new upload url for the file.
264
265
Returns:
266
str: Upload URL for this file
267
268
Raises:
269
TusCommunicationError: If server returns error or no location header
270
"""
271
```
272
273
## Usage Examples
274
275
### Basic Synchronous Upload
276
277
```python
278
from tusclient import client
279
280
# Create client and uploader
281
my_client = client.TusClient('http://tusd.tusdemo.net/files/')
282
uploader = my_client.uploader('/path/to/file.ext', chunk_size=1024*1024)
283
284
# Upload entire file
285
uploader.upload()
286
287
# Upload chunk by chunk with progress tracking
288
while uploader.offset < uploader.get_file_size():
289
uploader.upload_chunk()
290
progress = (uploader.offset / uploader.get_file_size()) * 100
291
print(f"Upload progress: {progress:.1f}%")
292
```
293
294
### Basic Asynchronous Upload
295
296
```python
297
import asyncio
298
from tusclient import client
299
300
async def upload_file():
301
my_client = client.TusClient('http://tusd.tusdemo.net/files/')
302
uploader = my_client.async_uploader('/path/to/file.ext', chunk_size=1024*1024)
303
304
# Upload entire file
305
await uploader.upload()
306
307
# Run async upload
308
asyncio.run(upload_file())
309
```
310
311
### Resumable Upload with Storage
312
313
```python
314
from tusclient import client
315
from tusclient.storage.filestorage import FileStorage
316
317
# Setup client with URL storage for resumability
318
storage = FileStorage('/tmp/tuspy_urls.db')
319
my_client = client.TusClient('http://tusd.tusdemo.net/files/')
320
321
uploader = my_client.uploader(
322
'/path/to/large_file.ext',
323
chunk_size=5*1024*1024, # 5MB chunks
324
store_url=True,
325
url_storage=storage,
326
retries=3,
327
retry_delay=10
328
)
329
330
try:
331
uploader.upload()
332
finally:
333
storage.close()
334
```
335
336
### Upload with Metadata
337
338
```python
339
from tusclient import client
340
341
my_client = client.TusClient('http://tusd.tusdemo.net/files/')
342
uploader = my_client.uploader(
343
'/path/to/file.pdf',
344
metadata={
345
'filename': 'document.pdf',
346
'filetype': 'application/pdf',
347
'author': 'John Doe'
348
},
349
chunk_size=1024*1024
350
)
351
352
uploader.upload()
353
```
354
355
### Partial Upload
356
357
```python
358
from tusclient import client
359
360
my_client = client.TusClient('http://tusd.tusdemo.net/files/')
361
uploader = my_client.uploader('/path/to/file.ext', chunk_size=1024*1024)
362
363
# Upload only first 50MB of file
364
uploader.upload(stop_at=50*1024*1024)
365
```
366
367
### Direct Uploader Usage
368
369
```python
370
from tusclient.uploader import Uploader
371
372
# Use uploader without client if URL is known
373
uploader = Uploader(
374
'/path/to/file.ext',
375
url='http://tusd.tusdemo.net/files/abcdef123456',
376
chunk_size=1024*1024
377
)
378
379
uploader.upload()
380
```