fix: non-range HTTP downloaded bytes exceeding total file size (#1317)

This commit is contained in:
Levi authored and GitHub committed 2026-03-18 18:53:49 +08:00
1 parent 3d20e818e5
commit 847e88881d
8 files changed
+124 -8

No files matched your search

+33 -1
View File
@@ -618,6 +618,7 @@ func (f *Fetcher) doStart() error {
for _, conn := range f.connections {
// Reset connections that can be retried
if !conn.Completed && conn.State != connCompleted {
f.resetConnectionForRestart(conn)
conn.State = connNotStarted
conn.failed = false
conn.retryTimes = 0
@@ -1413,6 +1414,27 @@ func (f *Fetcher) helpOtherConnection(helper *connection) bool {
return true
}
func (f *Fetcher) resetConnectionForRestart(conn *connection) {
if f.meta.Res.Range {
return
}
// Without range support a new request always starts from byte 0,
// so pause/retry must restart instead of continuing from the old offset.
if conn.Chunk == nil {
conn.Chunk = newChunk(0, 0)
} else {
conn.Chunk.Begin = 0
conn.Chunk.End = 0
conn.Chunk.Downloaded = 0
}
conn.Downloaded = 0
conn.Completed = false
conn.speed = 0
conn.lastSpeedCheck = 0
conn.lastSpeedDownload = 0
}
func (f *Fetcher) resumeConnections() {
// Collect connections to resume while holding the lock
var toResume []*connection
@@ -1436,6 +1458,7 @@ func (f *Fetcher) resumeConnections() {
continue
}
}
f.resetConnectionForRestart(conn)
// Reset the connection state for resume
conn.ctx, conn.cancel = context.WithCancel(f.ctx)
conn.State = connNotStarted
@@ -1475,7 +1498,16 @@ func (f *Fetcher) onDownloadComplete() {
// Check if all chunks are complete (no remaining bytes)
allChunksComplete := true
for _, conn := range f.connections {
if conn.Chunk != nil && conn.Chunk.remain() > 0 && !conn.Completed && conn.State != connCompleted {
needsMoreData := false
if f.meta.Res.Range {
needsMoreData = conn.Chunk != nil && conn.Chunk.remain() > 0
} else if f.meta.Res.Size > 0 {
needsMoreData = conn.Downloaded < f.meta.Res.Size
} else {
needsMoreData = !conn.Completed && conn.State != connCompleted
}
if needsMoreData && !conn.Completed && conn.State != connCompleted {
// This connection has remaining work and isn't done
// Check if it failed with 403 (server limit) - these can be ignored if other connections completed the work
if conn.State == connFailed && conn.failed {