|
9 | 9 | "context" |
10 | 10 | "encoding/base64" |
11 | 11 | "errors" |
12 | | - "fmt" |
| 12 | + "io" |
13 | 13 | "os" |
14 | 14 | "path" |
15 | 15 | "path/filepath" |
@@ -379,6 +379,20 @@ func (entry *Entry) availabilityPerDevice() (map[protocol.DeviceID]int, int, err |
379 | 379 | return deviceStatus, len(info.Blocks), nil |
380 | 380 | } |
381 | 381 |
|
| 382 | +type progressWriter struct { |
| 383 | + delegate DownloadDelegate |
| 384 | + out io.Writer |
| 385 | + written int |
| 386 | + total int |
| 387 | +} |
| 388 | + |
| 389 | +func (pw *progressWriter) Write(buf []byte) (n int, err error) { |
| 390 | + n, err = pw.out.Write(buf) |
| 391 | + pw.written += n |
| 392 | + pw.delegate.OnProgress(float64(pw.written) / float64(pw.total)) |
| 393 | + return |
| 394 | +} |
| 395 | + |
382 | 396 | /** Download this file to the specific location (should be outside the synced folder!) **/ |
383 | 397 | func (entry *Entry) Download(toPath string, delegate DownloadDelegate) { |
384 | 398 | go func() { |
@@ -410,33 +424,17 @@ func (entry *Entry) Download(toPath string, delegate DownloadDelegate) { |
410 | 424 | }() |
411 | 425 |
|
412 | 426 | delegate.OnProgress(0.0) |
413 | | - |
414 | | - for blockNo, block := range info.Blocks { |
415 | | - if delegate.IsCancelled() { |
416 | | - return |
417 | | - } |
418 | | - delegate.OnProgress(float64(block.Offset) / float64(info.Size)) |
419 | | - av, err := m.BlockAvailability(folderID, info, block) |
420 | | - if err != nil { |
421 | | - delegate.OnError(fmt.Sprintf("could not fetch availability for block %d: %s", blockNo, err.Error())) |
422 | | - return |
423 | | - } |
424 | | - if len(av) < 1 { |
425 | | - delegate.OnError(fmt.Sprintf("Part of the file is not available (block %d)", blockNo)) |
426 | | - return |
427 | | - } |
428 | | - |
429 | | - // Fetch the block |
430 | | - buf, err := m.DownloadBlock(context, av[0].ID, folderID, info.Name, int(blockNo), block, false) |
431 | | - if err != nil { |
432 | | - delegate.OnError(fmt.Sprintf("could not fetch block %d: %s", blockNo, err.Error())) |
433 | | - return |
434 | | - } |
435 | | - _, err = outFile.Write(buf) |
436 | | - if err != nil { |
437 | | - delegate.OnError(fmt.Sprintf("could not write block %d: %s", blockNo, err.Error())) |
438 | | - return |
439 | | - } |
| 427 | + mp := newMiniPuller(entry.Folder.client.Measurements, m) |
| 428 | + pw := progressWriter{ |
| 429 | + out: outFile, |
| 430 | + delegate: delegate, |
| 431 | + total: int(info.Size), |
| 432 | + written: 0, |
| 433 | + } |
| 434 | + err = mp.downloadInto(context, &pw, folderID, info) |
| 435 | + if err != nil { |
| 436 | + delegate.OnError(err.Error()) |
| 437 | + return |
440 | 438 | } |
441 | 439 | delegate.OnFinished(toPath) |
442 | 440 | }() |
|
0 commit comments