@@ -442,8 +442,7 @@ 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 # Bytes written to partition (in 4096-byte blocks)
446- self .bytes_received_so_far = 0 # Actual bytes received from network (for resume)
445+ self .bytes_written_so_far = 0 # Bytes written to partition (in complete 4096-byte blocks)
447446 self .total_size_expected = 0
448447
449448 # Internal state for chunk processing
@@ -524,9 +523,8 @@ async def _process_chunk(self, chunk):
524523 self .is_paused = True
525524 raise OSError (- 113 , "Network lost during download" )
526525
527- # Track total bytes received (for accurate resume position)
526+ # Track total bytes received
528527 self ._total_bytes_received += len (chunk )
529- self .bytes_received_so_far += len (chunk )
530528
531529 # Add chunk to buffer
532530 self ._chunk_buffer += chunk
@@ -603,14 +601,16 @@ async def download_and_install(self, url, progress_callback=None, speed_callback
603601 # Setup partition
604602 self ._setup_partition ()
605603
606- # Initialize block index from resume position (based on bytes written to partition)
604+ # Initialize block index from resume position
607605 self ._block_index = self .bytes_written_so_far // self .CHUNK_SIZE
608606
609- # Build headers for resume (based on bytes received from network)
607+ # Build headers for resume - use bytes_written_so_far (last complete block)
608+ # This ensures we re-download any partial/buffered data and overwrite any
609+ # potentially corrupted block from when the error occurred
610610 headers = None
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 } )" )
611+ if self .bytes_written_so_far > 0 :
612+ headers = {'Range' : f'bytes={ self .bytes_written_so_far } -' }
613+ print (f"UpdateDownloader: Resuming from byte { self .bytes_written_so_far } (last complete block )" )
614614
615615 # Get the download manager (use injected one for testing, or global)
616616 dm = self .download_manager if self .download_manager else DownloadManager
@@ -624,7 +624,7 @@ async def chunk_handler(chunk):
624624
625625 # For initial download, we need to get total size first
626626 # DownloadManager doesn't expose Content-Length directly, so we estimate
627- if self .bytes_received_so_far == 0 :
627+ if self .bytes_written_so_far == 0 :
628628 # We'll update total_size_expected as we download
629629 # For now, set a placeholder that will be updated
630630 self .total_size_expected = 0
@@ -655,7 +655,6 @@ async def chunk_handler(chunk):
655655 # Reset state for next download
656656 self .is_paused = False
657657 self .bytes_written_so_far = 0
658- self .bytes_received_so_far = 0
659658 self .total_size_expected = 0
660659 self ._current_partition = None
661660 self ._block_index = 0
@@ -676,34 +675,28 @@ async def chunk_handler(chunk):
676675 # Check if cancelled by user
677676 if "cancelled" in error_msg .lower ():
678677 result ['error' ] = error_msg
679- result ['bytes_written' ] = self .bytes_received_so_far # Report actual bytes received
678+ result ['bytes_written' ] = self .bytes_written_so_far
680679 result ['total_size' ] = self .total_size_expected
681680 # Check if this is a network error that should trigger pause
682681 elif self ._is_network_error (e ):
683682 print (f"UpdateDownloader: Network error ({ e } ), pausing download" )
684683
685- # Flush buffer before pausing to ensure all received data is written
686- # This prevents data loss/corruption on resume
684+ # Clear buffer - we'll re-download this data on resume
685+ # This ensures we overwrite any potentially corrupted block
687686 if self ._chunk_buffer :
688687 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
688+ print (f"UpdateDownloader: Discarding { buffer_len } bytes from buffer (will re-download on resume)" )
696689 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 } " )
698690
699691 self .is_paused = True
700692 result ['paused' ] = True
701- result ['bytes_written' ] = self .bytes_received_so_far # Report actual bytes received for resume
693+ result ['bytes_written' ] = self .bytes_written_so_far # Resume from last complete block
702694 result ['total_size' ] = self .total_size_expected
695+ print (f"UpdateDownloader: Will resume from byte { self .bytes_written_so_far } (last complete block)" )
703696 else :
704697 # Non-network error
705698 result ['error' ] = error_msg
706- result ['bytes_written' ] = self .bytes_received_so_far # Report actual bytes received
699+ result ['bytes_written' ] = self .bytes_written_so_far
707700 result ['total_size' ] = self .total_size_expected
708701 print (f"UpdateDownloader: Error during download: { e } " )
709702
0 commit comments