WebApi 文件下载服务端与客户端
简介
原帮助类代码参考 WebApi 帮助类,新增下载文件方法,使用 WPF 调用下载并回调显示下载进度。显示下载文件大小以及下载速度。
代码
服务端代码
服务端代码因项目而异,这段代码仅为示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
[HttpGet] public ActionResult DownloadFile(string FileName) { var vFileCompletePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FileName); if (!System.IO.File.Exists(vFileCompletePath)) { return Unauthorized("File does not exist!"); }
var vStream = System.IO.File.OpenRead(vFileCompletePath); var vProvider = new FileExtensionContentTypeProvider(); if (!vProvider.TryGetContentType(vFileCompletePath, out string? contentType)) { contentType = "application/octet-stream"; } return File(vStream, contentType); }
|
帮助类代码
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
|
public static async Task<bool> DownloadGetAsync(Uri baseAddress, string? requestUrl, IDictionary<string, object>? parameters, string saveFilePath, Action<object?, HttpProgressEventArgs>? progressAction = null, string? token = null) { ProgressMessageHandler progress = new ProgressMessageHandler(); progress.HttpReceiveProgress += (s, e) => { progressAction?.Invoke(s, e); };
var vHttpClient = HttpClientFactory.Create(progress); vHttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try { if (!string.IsNullOrEmpty(token)) { vHttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); } vHttpClient.Timeout = TimeSpan.FromMinutes(20);
var vBuilder = new StringBuilder(); vBuilder.Append(baseAddress); vBuilder.Append(requestUrl); if (parameters != null && parameters.Count >= 1) { vBuilder.Append('?'); int i = 0; foreach (var item in parameters) { if (i > 0) { vBuilder.Append('&'); } vBuilder.AppendFormat("{0}={1}", item.Key, item.Value); i++; } }
using var vResponse = await vHttpClient.GetAsync(vBuilder.ToString()); if (vResponse.IsSuccessStatusCode) { using var vFs = File.Create(saveFilePath); var vStream = await vResponse.Content.ReadAsStreamAsync(); vStream.CopyTo(vFs); vStream.Close(); vStream.Dispose(); vFs.Close(); vFs.Dispose(); return true; } else { return false; } } catch (Exception) { return false; } finally { vHttpClient.Dispose(); vHttpClient = null; GC.Collect(); } }
|
进度条样式
1 2 3 4 5
| <Grid> <ProgressBar x:Name="progressBar" HorizontalAlignment="Left" Height="13" Margin="10,10,0,0" VerticalAlignment="Top" Width="100" Maximum="1" Minimum="0"/> <Label x:Name="number" HorizontalAlignment="Left" Margin="10,28,0,0" VerticalAlignment="Top" Width="319" Height="41"/> <Label x:Name="number2" HorizontalAlignment="Left" Margin="10,58,0,0" VerticalAlignment="Top" Width="319" Height="41"/> </Grid>
|
调用下载
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
| private async void MainWindow_Loaded(object sender, RoutedEventArgs e) { string serverUrl = "https://localhost:7252/"; string requestUrl = "api/File/DownloadFile"; string savePath = @"D:\1.png";
var vParameters = new Dictionary<string, object> { { "FileName", "1.png" } }; var vDownload = await HttpClientHelper.DownloadGetAsync(new Uri(serverUrl), requestUrl, vParameters, savePath, DownloadProgressChanged); MessageBox.Show($"保存{(vDownload ? "成功" : "失败")}"); }
private void DownloadProgressChanged(object? arg1, HttpProgressEventArgs arg2) { this.Dispatcher.Invoke(new Action(() => { if (arg2.ProgressPercentage >= 0 && arg2.ProgressPercentage <= 100) { progressBar.Value = arg2.ProgressPercentage / 100.0; number.Content = $"{ByteChange(arg2.BytesTransferred)}/{ByteChange(arg2.TotalBytes)}"; CalcDownloadSpeed(DateTime.Now, arg2.BytesTransferred); } })); }
private DateTime lastTime = DateTime.Now; private long BytesTransferred = 0;
private void CalcDownloadSpeed(DateTime time, long bytesTransferred) { if (lastTime.Second != time.Second) { this.Dispatcher.Invoke(new Action(() => { number2.Content = $"Speed: {ByteChange(bytesTransferred - BytesTransferred)}/s"; }));
lastTime = time; BytesTransferred = bytesTransferred; } }
private string ByteChange(long? TotalBytes) { long kb = 1024; long mb = kb * kb; long gb = mb * kb; long tb = gb * kb;
if (TotalBytes >= tb) { return $"{Math.Round((decimal)TotalBytes / tb, 2)}TB"; } else if (TotalBytes >= gb) { return $"{Math.Round((decimal)TotalBytes / gb, 2)}GB"; } else if (TotalBytes >= mb) { return $"{Math.Round((decimal)TotalBytes / mb, 2)}MB"; } else if (TotalBytes >= kb) { return $"{Math.Round((decimal)TotalBytes / kb, 2)}KB"; } else { return $"{TotalBytes}B"; } }
|