Skip to content

Commit 0713cca

Browse files
committed
增加文件上传进度事件
1 parent a32235d commit 0713cca

File tree

3 files changed

+156
-16
lines changed

3 files changed

+156
-16
lines changed

WebApiClient/HttpResponseFile.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class HttpResponseFile : HttpResponseWrapper
1616
/// <summary>
1717
/// 下载进度变化事件
1818
/// </summary>
19-
public event EventHandler<DownloadProgressEventArgs> DownloadProgressChanged;
19+
public event EventHandler<ProgressEventArgs> DownloadProgressChanged;
2020

2121
/// <summary>
2222
/// 获取响应的友好文件名称
@@ -95,20 +95,20 @@ public async Task SaveAsAsync(Stream stream)
9595
var buffer = new byte[8 * 1024];
9696
var sourceStream = await this.HttpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
9797

98-
var args = new DownloadProgressEventArgs(current, this.FileSize, false);
98+
var args = new ProgressEventArgs(current, this.FileSize, false);
9999
this.DownloadProgressChanged?.Invoke(this, args);
100100

101101
while ((length = await sourceStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0)
102102
{
103103
current = current + length;
104104

105-
args = new DownloadProgressEventArgs(current, this.FileSize, false);
105+
args = new ProgressEventArgs(current, this.FileSize, false);
106106
this.DownloadProgressChanged?.Invoke(this, args);
107107

108108
await stream.WriteAsync(buffer, 0, length).ConfigureAwait(false);
109109
}
110110

111-
args = new DownloadProgressEventArgs(current, this.FileSize, true);
111+
args = new ProgressEventArgs(current, this.FileSize, true);
112112
this.DownloadProgressChanged?.Invoke(this, args);
113113
}
114114
}

WebApiClient/Parameterables/MulitpartFile.cs

Lines changed: 146 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ public class MulitpartFile : IApiParameterable
2828
/// </summary>
2929
private readonly string fileName;
3030

31+
/// <summary>
32+
/// 上传进度变化事件
33+
/// </summary>
34+
public event EventHandler<ProgressEventArgs> UploadProgressChanged;
35+
3136
/// <summary>
3237
/// 获取文件好友名称
3338
/// </summary>
@@ -100,23 +105,158 @@ public MulitpartFile(string localFilePath)
100105
/// <param name="parameter">特性关联的参数</param>
101106
async Task IApiParameterable.BeforeRequestAsync(ApiActionContext context, ApiParameterDescriptor parameter)
102107
{
103-
context.RequestMessage.AddMulitpartFile(this.GetStream(), parameter.Name, this.FileName, this.ContentType);
108+
context.RequestMessage.AddMulitpartFile(this.GetUploadStream(), parameter.Name, this.FileName, this.ContentType);
104109
await ApiTask.CompletedTask;
105110
}
106111

107112
/// <summary>
108113
/// 获取文件流
109114
/// </summary>
110115
/// <returns></returns>
111-
private Stream GetStream()
116+
private UploadStream GetUploadStream()
117+
{
118+
var inner = this.stream ?? new FileStream(this.filePath, FileMode.Open, FileAccess.Read);
119+
return new UploadStream(inner, this.RaiseUploadProgressChanged);
120+
}
121+
122+
/// <summary>
123+
/// 触发上传进度变化事件
124+
/// </summary>
125+
/// <param name="e"></param>
126+
private void RaiseUploadProgressChanged(ProgressEventArgs e)
127+
{
128+
this.UploadProgressChanged?.Invoke(this, e);
129+
}
130+
131+
132+
/// <summary>
133+
/// 表示上传数据流
134+
/// </summary>
135+
private class UploadStream : Stream
112136
{
113-
if (this.stream != null)
137+
/// <summary>
138+
/// 内部流
139+
/// </summary>
140+
private readonly Stream inner;
141+
142+
/// <summary>
143+
/// 总字节数
144+
/// </summary>
145+
private readonly long? totalBytes;
146+
147+
/// <summary>
148+
/// 进度事件处理者
149+
/// </summary>
150+
private readonly Action<ProgressEventArgs> eventArgsHandler;
151+
152+
/// <summary>
153+
/// 记录当前字节数
154+
/// </summary>
155+
private long currentBytes = 0L;
156+
157+
/// <summary>
158+
/// 上传数据流
159+
/// </summary>
160+
/// <param name="inner">内部流</param>
161+
/// <param name="eventArgsHandler">进度事件处理者</param>
162+
/// <exception cref="ArgumentNullException"></exception>
163+
public UploadStream(Stream inner, Action<ProgressEventArgs> eventArgsHandler)
114164
{
115-
return this.stream;
165+
this.inner = inner ?? throw new ArgumentNullException(nameof(inner));
166+
this.eventArgsHandler = eventArgsHandler ?? throw new ArgumentNullException(nameof(eventArgsHandler));
167+
168+
try
169+
{
170+
this.totalBytes = inner.Length;
171+
}
172+
catch (Exception) { }
116173
}
117-
else
174+
175+
/// <summary>
176+
/// 获取是否可读
177+
/// </summary>
178+
public override bool CanRead => this.inner.CanRead;
179+
180+
/// <summary>
181+
/// 获取是否可定位
182+
/// </summary>
183+
public override bool CanSeek => this.inner.CanSeek;
184+
185+
/// <summary>
186+
/// 获取是否可写
187+
/// </summary>
188+
public override bool CanWrite => this.inner.CanWrite;
189+
190+
/// <summary>
191+
/// 获取数据长度
192+
/// </summary>
193+
public override long Length => this.inner.Length;
194+
195+
/// <summary>
196+
/// 获取数据指针公交车
197+
/// </summary>
198+
public override long Position
199+
{
200+
get => this.inner.Position;
201+
set => this.inner.Position = value;
202+
}
203+
204+
/// <summary>
205+
/// 冲刷
206+
/// </summary>
207+
public override void Flush()
208+
{
209+
this.inner.Flush();
210+
}
211+
212+
/// <summary>
213+
/// 读取数据
214+
/// </summary>
215+
/// <param name="buffer"></param>
216+
/// <param name="offset"></param>
217+
/// <param name="count"></param>
218+
/// <returns></returns>
219+
public override int Read(byte[] buffer, int offset, int count)
220+
{
221+
var length = this.inner.Read(buffer, offset, count);
222+
var isCompleted = length == 0;
223+
224+
this.currentBytes = this.currentBytes + length;
225+
var args = new ProgressEventArgs(this.currentBytes, this.totalBytes, isCompleted);
226+
this.eventArgsHandler.Invoke(args);
227+
228+
return length;
229+
}
230+
231+
/// <summary>
232+
/// 定位
233+
/// </summary>
234+
/// <param name="offset"></param>
235+
/// <param name="origin"></param>
236+
/// <returns></returns>
237+
public override long Seek(long offset, SeekOrigin origin)
238+
{
239+
return this.inner.Seek(offset, origin);
240+
}
241+
242+
/// <summary>
243+
/// 设置长度
244+
/// </summary>
245+
/// <param name="value"></param>
246+
public override void SetLength(long value)
247+
{
248+
this.inner.SetLength(value);
249+
}
250+
251+
/// <summary>
252+
/// 写入数据
253+
/// </summary>
254+
/// <param name="buffer"></param>
255+
/// <param name="offset"></param>
256+
/// <param name="count"></param>
257+
public override void Write(byte[] buffer, int offset, int count)
118258
{
119-
return new FileStream(this.filePath, FileMode.Open, FileAccess.Read);
259+
this.inner.Write(buffer, offset, count);
120260
}
121261
}
122262
}

WebApiClient/DownloadProgressEventArgs.cs renamed to WebApiClient/ProgressEventArgs.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
namespace WebApiClient
44
{
55
/// <summary>
6-
/// 表示下载进度
6+
/// 表示上传或下载进度
77
/// </summary>
8-
public class DownloadProgressEventArgs : EventArgs
8+
public class ProgressEventArgs : EventArgs
99
{
1010
/// <summary>
11-
/// 获取当前收到的字节数
11+
/// 获取当前完成的字节数
1212
/// </summary>
1313
public long CurrentBytes { get; }
1414

@@ -38,12 +38,12 @@ public double Progress
3838
}
3939

4040
/// <summary>
41-
/// 下载进度
41+
/// 上传或下载进度
4242
/// </summary>
43-
/// <param name="current">当前收到的字节数</param>
43+
/// <param name="current">当前完成的字节数</param>
4444
/// <param name="total">总字节数</param>
4545
/// <param name="isCompleted">是否已完成</param>
46-
public DownloadProgressEventArgs(long current, long? total, bool isCompleted)
46+
public ProgressEventArgs(long current, long? total, bool isCompleted)
4747
{
4848
this.CurrentBytes = current;
4949
this.TotalBytes = total;

0 commit comments

Comments
 (0)