@@ -279,13 +279,15 @@ def download_project(
279279 filter_glob : str = None ,
280280 throw_on_error : bool = False ,
281281 show_progress : bool = False ,
282+ force_download : bool = False ,
282283 ) -> List [Dict ]:
283284 """Download the specified project files into the destination dir.
284285
285286 Args:
286287 project_id: id of the project to be downloaded
287288 local_dir: destination directory where the files will be downloaded
288289 filter_glob: if specified, download only the files which match the glob, otherwise download all
290+ force_download (bool, optional): Download file even if it already exists locally. Defaults to False.
289291 """
290292
291293 files = self .list_remote_files (project_id )
@@ -298,6 +300,7 @@ def download_project(
298300 filter_glob ,
299301 throw_on_error ,
300302 show_progress ,
303+ force_download ,
301304 )
302305
303306 def list_jobs (self , project_id : str , job_type : JobTypes = None ) -> Dict [str , Any ]:
@@ -442,13 +445,15 @@ def package_download(
442445 filter_glob : str = None ,
443446 throw_on_error : bool = False ,
444447 show_progress : bool = False ,
448+ force_download : bool = False ,
445449 ) -> List [Dict ]:
446450 """Download the specified project packaged files into the destination dir.
447451
448452 Args:
449453 project_id: id of the project to be downloaded
450454 local_dir: destination directory where the files will be downloaded
451455 filter_glob: if specified, download only packaged files which match the glob, otherwise download all
456+ force_download (bool, optional): Download file even if it already exists locally. Defaults to False.
452457 """
453458 project_status = self .package_latest (project_id )
454459
@@ -467,6 +472,7 @@ def package_download(
467472 filter_glob ,
468473 throw_on_error ,
469474 show_progress ,
475+ force_download ,
470476 )
471477
472478 def download_files (
@@ -478,6 +484,7 @@ def download_files(
478484 filter_glob : str = None ,
479485 throw_on_error : bool = False ,
480486 show_progress : bool = False ,
487+ force_download : bool = False ,
481488 ) -> List [Dict ]:
482489 """Download project files.
483490
@@ -489,7 +496,7 @@ def download_files(
489496 filter_glob (str, optional): Download only files matching the glob pattern. If None download all. Defaults to None.
490497 throw_on_error (bool, optional): Throw if download error occurres. Defaults to False.
491498 show_progress (bool, optional): Show progress bar in the console. Defaults to False.
492-
499+ force_download (bool, optional): Download file even if it already exists locally. Defaults to False.
493500 Raises:
494501 QFieldCloudException: if throw_on_error is True, throw an error if a download request fails.
495502
@@ -515,7 +522,9 @@ def download_files(
515522 download_type ,
516523 local_filename ,
517524 file ["name" ],
525+ file .get ("md5sum" , None ),
518526 show_progress ,
527+ force_download ,
519528 )
520529 file ["status" ] = FileTransferStatus .SUCCESS
521530 except QfcRequestException as err :
@@ -541,7 +550,9 @@ def download_file(
541550 download_type : FileTransferType ,
542551 local_filename : Path ,
543552 remote_filename : Path ,
553+ remote_md5sum : str ,
544554 show_progress : bool ,
555+ force_download : bool = False ,
545556 ) -> requests .Response :
546557 """Download a single project file.
547558
@@ -551,13 +562,29 @@ def download_file(
551562 local_filename (Path): Local filename
552563 remote_filename (Path): Remote filename
553564 show_progress (bool): Show progressbar in the console
565+ force_download (bool, optional): Download file even if it already exists locally. Defaults to False.
554566
555567 Raises:
556568 NotImplementedError: Raised if unknown `download_type` is passed
557569
558570 Returns:
559571 requests.Response: the response object
560572 """
573+
574+ if (not force_download ) and local_filename .exists () and remote_md5sum :
575+ with open (local_filename , "rb" ) as f :
576+ file_hash = hashlib .md5 ()
577+ chunk = f .read (8192 )
578+ while chunk :
579+ file_hash .update (chunk )
580+ chunk = f .read (8192 )
581+ if file_hash .hexdigest () == remote_md5sum :
582+ if show_progress :
583+ print (f"{ remote_filename } : Already present locally. Download skipped." )
584+ else :
585+ logging .info (f'Skipping downloading file "{ remote_filename } " because it is already present locally' )
586+ return
587+
561588 if download_type == FileTransferType .PROJECT :
562589 url = f"files/{ project_id } /{ remote_filename } "
563590 elif download_type == FileTransferType .PACKAGE :
0 commit comments