@@ -442,7 +442,8 @@ def __init__(self, partition_module=None, connectivity_manager=None, download_ma
442442
443443 # Download state for pause/resume
444444 self .is_paused = False
445- self .bytes_written_so_far = 0
445+ self .bytes_written_so_far = 0 # Bytes written to partition (in 4096-byte blocks)
446+ self .bytes_received_so_far = 0 # Actual bytes received from network (for resume)
446447 self .total_size_expected = 0
447448
448449 # Internal state for chunk processing
@@ -523,8 +524,9 @@ async def _process_chunk(self, chunk):
523524 self .is_paused = True
524525 raise OSError (- 113 , "Network lost during download" )
525526
526- # Track total bytes received
527+ # Track total bytes received (for accurate resume position)
527528 self ._total_bytes_received += len (chunk )
529+ self .bytes_received_so_far += len (chunk )
528530
529531 # Add chunk to buffer
530532 self ._chunk_buffer += chunk
@@ -601,14 +603,14 @@ async def download_and_install(self, url, progress_callback=None, speed_callback
601603 # Setup partition
602604 self ._setup_partition ()
603605
604- # Initialize block index from resume position
606+ # Initialize block index from resume position (based on bytes written to partition)
605607 self ._block_index = self .bytes_written_so_far // self .CHUNK_SIZE
606608
607- # Build headers for resume
609+ # Build headers for resume (based on bytes received from network)
608610 headers = None
609- if self .bytes_written_so_far > 0 :
610- headers = {'Range' : f'bytes={ self .bytes_written_so_far } -' }
611- print (f"UpdateDownloader: Resuming from byte { self .bytes_written_so_far } " )
611+ if self .bytes_received_so_far > 0 :
612+ headers = {'Range' : f'bytes={ self .bytes_received_so_far } -' }
613+ print (f"UpdateDownloader: Resuming from byte { self .bytes_received_so_far } (written: { self . bytes_written_so_far } ) " )
612614
613615 # Get the download manager (use injected one for testing, or global)
614616 dm = self .download_manager if self .download_manager else DownloadManager
@@ -622,7 +624,7 @@ async def chunk_handler(chunk):
622624
623625 # For initial download, we need to get total size first
624626 # DownloadManager doesn't expose Content-Length directly, so we estimate
625- if self .bytes_written_so_far == 0 :
627+ if self .bytes_received_so_far == 0 :
626628 # We'll update total_size_expected as we download
627629 # For now, set a placeholder that will be updated
628630 self .total_size_expected = 0
@@ -653,6 +655,7 @@ async def chunk_handler(chunk):
653655 # Reset state for next download
654656 self .is_paused = False
655657 self .bytes_written_so_far = 0
658+ self .bytes_received_so_far = 0
656659 self .total_size_expected = 0
657660 self ._current_partition = None
658661 self ._block_index = 0
@@ -673,19 +676,34 @@ async def chunk_handler(chunk):
673676 # Check if cancelled by user
674677 if "cancelled" in error_msg .lower ():
675678 result ['error' ] = error_msg
676- result ['bytes_written' ] = self .bytes_written_so_far
679+ result ['bytes_written' ] = self .bytes_received_so_far # Report actual bytes received
677680 result ['total_size' ] = self .total_size_expected
678681 # Check if this is a network error that should trigger pause
679682 elif self ._is_network_error (e ):
680683 print (f"UpdateDownloader: Network error ({ e } ), pausing download" )
684+
685+ # Flush buffer before pausing to ensure all received data is written
686+ # This prevents data loss/corruption on resume
687+ if self ._chunk_buffer :
688+ buffer_len = len (self ._chunk_buffer )
689+ print (f"UpdateDownloader: Flushing { buffer_len } bytes from buffer before pause" )
690+ # Pad to 4096 bytes and write
691+ padded = self ._chunk_buffer + b'\xFF ' * (self .CHUNK_SIZE - buffer_len )
692+ if not self .simulate :
693+ self ._current_partition .writeblocks (self ._block_index , padded )
694+ self ._block_index += 1
695+ self .bytes_written_so_far += self .CHUNK_SIZE
696+ self ._chunk_buffer = b''
697+ print (f"UpdateDownloader: Buffer flushed, bytes_written_so_far now: { self .bytes_written_so_far } , bytes_received: { self .bytes_received_so_far } " )
698+
681699 self .is_paused = True
682700 result ['paused' ] = True
683- result ['bytes_written' ] = self .bytes_written_so_far
701+ result ['bytes_written' ] = self .bytes_received_so_far # Report actual bytes received for resume
684702 result ['total_size' ] = self .total_size_expected
685703 else :
686704 # Non-network error
687705 result ['error' ] = error_msg
688- result ['bytes_written' ] = self .bytes_written_so_far
706+ result ['bytes_written' ] = self .bytes_received_so_far # Report actual bytes received
689707 result ['total_size' ] = self .total_size_expected
690708 print (f"UpdateDownloader: Error during download: { e } " )
691709
0 commit comments