@@ -113,14 +113,11 @@ class RecordLinks(TypedDict):
113113 reserve_doi : str
114114
115115
116- # AWS S3 multipart limits (used by Invenio RDM)
117- MIN_UPLOAD_PART_SIZE = 50 * 1024 * 1024 # 50 MiB
116+ # AWS S3 multipart default limits (used by Invenio RDM)
117+ MIN_UPLOAD_PART_SIZE = 5 * 1024 * 1024 # 5 MiB
118118MAX_UPLOAD_PART_SIZE = 5 * 1024 ** 3 # 5 GiB
119119MAX_UPLOAD_PARTS = 10_000
120120
121- # Default threshold for using multipart upload (100 MiB)
122- DEFAULT_MULTIPART_THRESHOLD = 100 * 1024 * 1024
123-
124121
125122def calculate_multipart_params (file_size : int , preferred_part_size : int | None = None ) -> tuple [int , int ]:
126123 """Calculate optimal parts count and part size for multipart upload.
@@ -393,16 +390,12 @@ def upload_file_to_draft_container(
393390 context : FilesSourceRuntimeContext [RDMFileSourceConfiguration ],
394391 ):
395392 file_size = os .path .getsize (file_path )
396- threshold = context .config .multipart_threshold
397-
398- # Use default threshold if not configured
399- if threshold is None or threshold <= 0 :
400- threshold = DEFAULT_MULTIPART_THRESHOLD
401-
402- use_multipart = file_size >= threshold
403393
394+ threshold_mb = context .config .multipart_threshold
395+ # Convert threshold from MB to bytes (config value is always in MB)
396+ threshold_bytes = threshold_mb * 1024 * 1024 if threshold_mb else None
397+ use_multipart = file_size >= threshold_bytes if threshold_bytes else False
404398 if use_multipart :
405- log .info (f"Using multipart upload for file '{ filename } ' ({ file_size } bytes >= threshold { threshold } )" )
406399 self ._upload_file_multipart (record_id , filename , file_path , file_size , context )
407400 else :
408401 self ._upload_file_single (record_id , filename , file_path , context , file_size )
@@ -436,11 +429,10 @@ def _upload_file_single(
436429 response = requests .put (upload_file_content_url , data = file , headers = headers )
437430 # Handle 413 (Payload Too Large) - suggest using multipart upload
438431 if response .status_code == 413 :
439- threshold_mb = DEFAULT_MULTIPART_THRESHOLD / (1024 * 1024 )
440432 raise Exception (
441433 f"Failed to upload file '{ filename } ' ({ file_size } bytes): HTTP 413 Payload Too Large. "
442434 f"The server rejected the upload because the file is too large for a single request. "
443- f"Please configure 'multipart_threshold' to { threshold_mb } MB or lower to enable multipart upload for files of this size."
435+ f"Please configure 'multipart_threshold' in the file source configuration to enable multipart upload for files of this size."
444436 )
445437 self ._ensure_response_has_expected_status_code (response , 200 )
446438
@@ -465,7 +457,9 @@ def _upload_file_multipart(
465457 4. Upload parts (parallel for > 2 parts)
466458 5. POST to commit URL
467459 """
468- preferred_part_size = context .config .multipart_chunk_size
460+ preferred_part_size_mb = context .config .multipart_chunk_size
461+ # Convert chunk size from MB to bytes (config value is always in MB)
462+ preferred_part_size = preferred_part_size_mb * 1024 * 1024 if preferred_part_size_mb else None
469463 num_parts , part_size = calculate_multipart_params (file_size , preferred_part_size )
470464
471465 log .info (f"Multipart upload: { num_parts } parts of { part_size } bytes each for '{ filename } '" )
@@ -474,7 +468,6 @@ def _upload_file_multipart(
474468 upload_file_url = record ["links" ]["files" ]
475469 headers = self ._get_request_headers (context , auth_required = True )
476470
477- # Initialize multipart upload with transfer metadata
478471 file_metadata = {
479472 "key" : filename ,
480473 "size" : file_size ,
@@ -499,13 +492,8 @@ def _upload_file_multipart(
499492 )
500493
501494 # Sort part links by part number to ensure correct ordering
502- # Invenio uses 'part' key, not 'part_number'
503495 part_links = sorted (part_links , key = lambda p : p .get ("part" , 0 ))
504-
505- # Upload parts
506496 self ._upload_parts (file_path , file_size , part_size , part_links , headers )
507-
508- # Commit multipart upload
509497 response = requests .post (commit_url , json = {}, headers = headers )
510498 self ._ensure_response_has_expected_status_code (response , 200 )
511499 log .info (f"Multipart upload completed for '{ filename } '" )
0 commit comments