Skip to content

Commit 3647622

Browse files
authored
Merge pull request #88 from opengisch/QF-6866-multipart_encoder
feat: add multipart encoder when uploading (large) files
2 parents 1ad452d + c8f94f1 commit 3647622

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

qfieldcloud_sdk/sdk.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import requests
1212
import urllib3
1313
from requests.adapters import HTTPAdapter, Retry
14+
from requests_toolbelt.multipart.encoder import MultipartEncoderMonitor
1415

1516
from .interfaces import QfcException, QfcRequest, QfcRequestException
1617
from .utils import calc_etag, log, add_trailing_slash_to_url
@@ -665,21 +666,39 @@ def upload_file(
665666
# if the filepath is invalid, it will throw a new error `pathvalidate.ValidationError`
666667
is_valid_filepath(str(local_filename))
667668

669+
local_file_size = local_filename.stat().st_size
668670
with open(local_filename, "rb") as local_file:
669-
upload_file = local_file
671+
encoder_params = {}
672+
670673
if show_progress:
671674
from tqdm import tqdm
672-
from tqdm.utils import CallbackIOWrapper
673675

674676
progress_bar = tqdm(
675-
total=local_filename.stat().st_size,
677+
total=local_file_size,
676678
unit_scale=True,
677-
desc=local_filename.stem,
679+
unit="B",
680+
desc=f'Uploading "{remote_filename}"...',
678681
)
679-
upload_file = CallbackIOWrapper(progress_bar.update, local_file, "read")
682+
683+
def cb(monitor: MultipartEncoderMonitor) -> None:
684+
progress_bar.n = monitor.bytes_read
685+
progress_bar.refresh()
686+
687+
encoder_params["callback"] = cb
680688
else:
681689
logger.info(f'Uploading file "{remote_filename}"…')
682690

691+
multipart_data = MultipartEncoderMonitor.from_fields(
692+
fields={
693+
"file": (
694+
str(remote_filename),
695+
local_file,
696+
None,
697+
),
698+
},
699+
**encoder_params,
700+
)
701+
683702
if upload_type == FileTransferType.PROJECT:
684703
url = f"files/{project_id}/{remote_filename}"
685704
elif upload_type == FileTransferType.PACKAGE:
@@ -695,8 +714,10 @@ def upload_file(
695714
return self._request(
696715
"POST",
697716
url,
698-
files={
699-
"file": upload_file,
717+
data=multipart_data,
718+
headers={
719+
"Content-Type": multipart_data.content_type,
720+
"Accept": "application/json",
700721
},
701722
)
702723

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ charset-normalizer>=3.2.0
33
click>=8.1.5
44
idna>=3.4
55
requests>=2.31.0
6+
requests-toolbelt>=1.0.0
67
tqdm>=4.65.0
78
urllib3>=2.0.7
89
pathvalidate>=3.2.1

0 commit comments

Comments
 (0)