-
Notifications
You must be signed in to change notification settings - Fork 447
/
Copy pathHttpResponseMessageExtensions.cs
125 lines (112 loc) · 4.95 KB
/
HttpResponseMessageExtensions.cs
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
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using WebApiClientCore;
using WebApiClientCore.Internals;
namespace System.Net.Http
{
/// <summary>
/// HttpResponseMessage扩展
/// </summary>
public static class HttpResponseMessageExtensions
{
/// <summary>
/// 读取响应头
/// </summary>
/// <param name="response">响应信息</param>
/// <returns></returns>
public static string GetHeadersString(this HttpResponseMessage response)
{
Span<char> buffer = stackalloc char[4 * 1024];
var builder = new ValueStringBuilder(buffer);
builder.AppendLine($"HTTP/{response.Version} {(int)response.StatusCode} {response.ReasonPhrase}");
builder.Append(response.Headers.ToString());
if (response.Content != null)
{
builder.Append(response.Content.Headers.ToString());
}
return builder.ToString();
}
/// <summary>
/// 保存到指定路径
/// </summary>
/// <param name="httpResponse"></param>
/// <param name="filePath">文件路径和文件名</param>
/// <param name="cancellationToken">取消令牌</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="OperationCanceledException"></exception>
/// <returns></returns>
public static async Task SaveAsAsync(this HttpResponseMessage httpResponse, string filePath, CancellationToken cancellationToken = default)
{
if (string.IsNullOrEmpty(filePath) == true)
{
throw new ArgumentNullException(nameof(filePath));
}
var dir = Path.GetDirectoryName(filePath);
if (string.IsNullOrEmpty(dir) == false)
{
Directory.CreateDirectory(dir);
}
using var fileStream = File.OpenWrite(filePath);
await httpResponse.SaveAsAsync(fileStream, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// 保存到目标流
/// </summary>
/// <param name="httpResponse"></param>
/// <param name="destination">目标流</param>
/// <param name="cancellationToken">取消令牌</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="OperationCanceledException"></exception>
/// <returns></returns>
public static async Task SaveAsAsync(this HttpResponseMessage httpResponse, Stream destination, CancellationToken cancellationToken = default)
{
if (destination == null)
{
throw new ArgumentNullException(nameof(destination));
}
var source = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
await source.CopyToAsync(destination, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// 保存到目标流
/// </summary>
/// <param name="httpResponse"></param>
/// <param name="destination">目标流</param>
/// <param name="progressChanged">进度变化</param>
/// <param name="cancellationToken">取消令牌</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="OperationCanceledException"></exception>
/// <returns></returns>
public static async Task SaveAsAsync(this HttpResponseMessage httpResponse, Stream destination, Action<HttpProgress> progressChanged, CancellationToken cancellationToken = default)
{
if (destination == null)
{
throw new ArgumentNullException(nameof(destination));
}
var recvSize = 0L;
var isCompleted = false;
var fileSize = httpResponse.Content.Headers.ContentLength;
var buffer = new byte[8 * 1024];
var source = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
while (isCompleted == false && cancellationToken.IsCancellationRequested == false)
{
var length = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false);
if (length == 0)
{
fileSize ??= recvSize;
isCompleted = true;
}
else
{
recvSize += length;
await destination.WriteAsync(buffer, 0, length, cancellationToken).ConfigureAwait(false);
await destination.FlushAsync(cancellationToken).ConfigureAwait(false);
}
progressChanged.Invoke(new HttpProgress(fileSize, recvSize, isCompleted));
}
}
}
}