Synkronisér kun hvis SharePoint-filen er nyere end lokal kopi
- Implementerer sammenligning af lastModifiedDateTime fra SharePoint med lokal mtime - Konverterer ISO8601 UTC-tidsstempler til unix timestamp for præcis sammenligning - Tilføjer 1-sekunds tolerance for at håndtere filsystemets tidspræcision - Sikrer at data kun hentes ned hvis kilden er opdateret, eller hvis lokal fil er korrupt
This commit is contained in:
@@ -211,7 +211,7 @@ def get_fresh_download_url(app, drive_id, item_id):
|
|||||||
|
|
||||||
return None, "Item returned but '@microsoft.graph.downloadUrl' was missing after 3 attempts."
|
return None, "Item returned but '@microsoft.graph.downloadUrl' was missing after 3 attempts."
|
||||||
|
|
||||||
def download_single_file(app, drive_id, item_id, local_path, expected_size, display_name, remote_hash=None, initial_url=None):
|
def download_single_file(app, drive_id, item_id, local_path, expected_size, display_name, remote_hash=None, initial_url=None, remote_mtime_str=None):
|
||||||
try:
|
try:
|
||||||
file_mode = 'wb'
|
file_mode = 'wb'
|
||||||
resume_header = {}
|
resume_header = {}
|
||||||
@@ -220,14 +220,30 @@ def download_single_file(app, drive_id, item_id, local_path, expected_size, disp
|
|||||||
|
|
||||||
if os.path.exists(local_path):
|
if os.path.exists(local_path):
|
||||||
existing_size = os.path.getsize(local_path)
|
existing_size = os.path.getsize(local_path)
|
||||||
|
local_mtime = os.path.getmtime(local_path)
|
||||||
|
|
||||||
|
# Konvertér SharePoint ISO8601 UTC tid (f.eks. 2024-03-29T12:00:00Z) til unix timestamp
|
||||||
|
# Vi fjerner 'Z' og bruger datetime.fromisoformat
|
||||||
|
remote_mtime = datetime.fromisoformat(remote_mtime_str.replace('Z', '+00:00')).timestamp()
|
||||||
|
|
||||||
|
# Hvis filen findes, har rigtig størrelse OG lokal er ikke ældre end remote -> SKIP
|
||||||
if existing_size == expected_size:
|
if existing_size == expected_size:
|
||||||
|
if local_mtime >= (remote_mtime - 1): # Vi tillader 1 sekuds difference pga. filsystem-præcision
|
||||||
if verify_integrity(local_path, remote_hash):
|
if verify_integrity(local_path, remote_hash):
|
||||||
logger.info(f"Skipped (complete): {display_name}")
|
logger.info(f"Skipped (up-to-date): {display_name}")
|
||||||
return True, None
|
return True, None
|
||||||
else:
|
else:
|
||||||
logger.warning(f"Hash mismatch on existing file: {display_name}. Re-downloading.")
|
logger.warning(f"Hash mismatch on existing file: {display_name}. Re-downloading.")
|
||||||
existing_size = 0
|
existing_size = 0
|
||||||
|
else:
|
||||||
|
logger.info(f"Update available: {display_name} (Remote is newer)")
|
||||||
|
existing_size = 0
|
||||||
elif existing_size < expected_size:
|
elif existing_size < expected_size:
|
||||||
|
# Ved resume tjekker vi også om kilden er ændret siden vi startede
|
||||||
|
if local_mtime < (remote_mtime - 1):
|
||||||
|
logger.warning(f"Remote file changed during partial download: {display_name}. Restarting.")
|
||||||
|
existing_size = 0
|
||||||
|
else:
|
||||||
logger.info(f"Resuming: {display_name} from {format_size(existing_size)}")
|
logger.info(f"Resuming: {display_name} from {format_size(existing_size)}")
|
||||||
resume_header = {'Range': f'bytes={existing_size}-'}
|
resume_header = {'Range': f'bytes={existing_size}-'}
|
||||||
file_mode = 'ab'
|
file_mode = 'ab'
|
||||||
@@ -306,12 +322,13 @@ def process_item_list(app, drive_id, item_path, local_root_path, report, executo
|
|||||||
item_id = item['id']
|
item_id = item['id']
|
||||||
download_url = item.get('@microsoft.graph.downloadUrl')
|
download_url = item.get('@microsoft.graph.downloadUrl')
|
||||||
remote_hash = item.get('file', {}).get('hashes', {}).get('quickXorHash')
|
remote_hash = item.get('file', {}).get('hashes', {}).get('quickXorHash')
|
||||||
|
remote_mtime = item.get('lastModifiedDateTime')
|
||||||
|
|
||||||
future = executor.submit(
|
future = executor.submit(
|
||||||
download_single_file,
|
download_single_file,
|
||||||
app, drive_id, item_id,
|
app, drive_id, item_id,
|
||||||
local_path, item['size'], display_path,
|
local_path, item['size'], display_path,
|
||||||
remote_hash, download_url
|
remote_hash, download_url, remote_mtime
|
||||||
)
|
)
|
||||||
futures[future] = display_path
|
futures[future] = display_path
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user