-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathFileTransferProgressBar.cs
More file actions
executable file
·132 lines (106 loc) · 4.57 KB
/
FileTransferProgressBar.cs
File metadata and controls
executable file
·132 lines (106 loc) · 4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
using System;
using System.Linq;
using System.Threading;
namespace AaronLuna.ConsoleProgressBar
{
public class FileTransferProgressBar : ConsoleProgressBar
{
private long _lastReportTicks;
public FileTransferProgressBar(long fileSizeInBytes, TimeSpan timeout)
{
_lastReportTicks = DateTime.Now.Ticks;
FileSizeInBytes = fileSizeInBytes;
BytesReceived = 0;
TimeSpanFileStalled = timeout;
DisplayBytes = true;
Timer = new Timer(TimerHandler);
// A progress bar is only for temporary display in a console window.
// If the console output is redirected to a file, draw nothing.
// Otherwise, we'll end up with a lot of garbage in the target file.
if (!Console.IsOutputRedirected)
{
ResetTimer();
}
}
public long FileSizeInBytes { get; set; }
public long BytesReceived { get; set; }
public TimeSpan TimeSpanFileStalled { get; set; }
public bool DisplayBytes { get; set; }
public event EventHandler<ProgressEventArgs> FileTransferStalled;
public new void Report(double value)
{
var ticks = DateTime.Now.Ticks;
Interlocked.Exchange(ref _lastReportTicks, ticks);
// Make sure value is in [0..1] range
value = Math.Max(0, Math.Min(1, value));
Interlocked.Exchange(ref CurrentProgress, value);
}
private void TimerHandler(object state)
{
lock (Timer)
{
if (Disposed) return;
var elapsedTicks = DateTime.Now.Ticks - _lastReportTicks;
var elapsed = TimeSpan.FromTicks(elapsedTicks);
UpdateText(GetProgressBarText(CurrentProgress));
ResetTimer();
if (elapsed < TimeSpanFileStalled) return;
FileTransferStalled?.Invoke(this,
new ProgressEventArgs
{
LastDataReceived = new DateTime(_lastReportTicks),
TimeOutTriggered = DateTime.Now
});
}
}
private string GetProgressBarText(double currentProgress)
{
const string singleSpace = " ";
var numBlocksCompleted = (int) (currentProgress * NumberOfBlocks);
var completedBlocks =
Enumerable.Range(0, numBlocksCompleted).Aggregate(
string.Empty,
(current, _) => current + CompletedBlock);
var incompleteBlocks =
Enumerable.Range(0, NumberOfBlocks - numBlocksCompleted).Aggregate(
string.Empty,
(current, _) => current + IncompleteBlock);
var progressBar =
$"{StartBracket}{completedBlocks}{incompleteBlocks}{EndBracket}";
var percent = $"{currentProgress:P0}".PadLeft(4, '\u00a0');
var fileSizeInBytes = FileSizeToString(FileSizeInBytes);
var padLength = fileSizeInBytes.Length;
var bytesReceived = FileSizeToString(BytesReceived)
.PadLeft(padLength, '\u00a0');
var bytes = $"{bytesReceived} of {fileSizeInBytes}";
var animationFrame =
AnimationSequence[AnimationIndex++ % AnimationSequence.Length];
var animation = $"{animationFrame}";
progressBar = DisplayBar
? progressBar + singleSpace
: string.Empty;
percent = DisplayPercentComplete
? percent + singleSpace
: string.Empty;
bytes = DisplayBytes
? bytes + singleSpace
: string.Empty;
if (!DisplayAnimation || currentProgress is 1)
{
animation = string.Empty;
}
return progressBar + bytes + percent + animation;
}
// not worthwhile referencing a DLL for just this one method
public static string FileSizeToString(long fileSizeInBytes)
{
if ((double) fileSizeInBytes > 1073741824.0)
return $"{(object) ((double) fileSizeInBytes / 1073741824.0):F2} GB";
return (double) fileSizeInBytes > 1048576.0
? $"{(object) ((double) fileSizeInBytes / 1048576.0):F2} MB"
: ((double) fileSizeInBytes > 1024.0
? $"{(object) ((double) fileSizeInBytes / 1024.0):F2} KB"
: $"{(object) fileSizeInBytes} bytes");
}
}
}