6.10上传文件资源

在互联网应用中,用户上传文件是一项常见需求,涵盖设置头像、发布图文动态、上传相册至网盘、分享 Vlog 到视频社区等场景。以下展示了多种文件上传的实现方式。

上传文件资源#

在互联网应用中,用户上传文件是一项常见需求,涵盖设置头像、发布图文动态、上传相册至网盘、分享 Vlog 到视频社区等场景。以下展示了多种文件上传的实现方式。

使用 Form 表单方式上传#

cs
await httpRemoteService.PostAsync("https://localhost:7044/HttpRemote/AddFile", builder => builder    .SetMultipartContent(multipart => multipart        .AddFileAsStream(@"C:\Workspaces\httptest.jpg", "file")));

若需上传多个文件,只需在 multipart 中继续添加(需保持表单名一致,如 files):

cs
await httpRemoteService.PostAsync("https://localhost:7044/HttpRemote/AddFiles", builder => builder    .SetMultipartContent(multipart => multipart        .AddFileAsStream(@"C:\Workspaces\httptest.jpg", "files")        .AddFileFromRemote("https://furion.net/img/furionlogo.png", "files")));

此外,还支持使用构建器模式,以及获取上传文件的返回值。更多详情可参考第 19.2.1 节。

cs
// 使用构建器模式await httpRemoteService.SendAsync(HttpRequestBuilder.Post("https://localhost:7044/HttpRemote/AddFile")    .SetMultipartContent(multipart => multipart        .AddFileAsStream(@"C:\Workspaces\httptest.jpg", "file")));// 更多详细用法可参考第 19.2.1 节

然而,这种上传文件资源的方式在面对多种复杂场景时显得不够灵活,例如无法实时追踪上传进度、限制上传文件类型和大小的情况,以及实现断点续传等。此外,它还可能需要开发者编写更多的额外代码。因此,框架中集成了专门设计用于上传文件资源的功能,以应对这些问题。

利用框架内置的专用上传功能进行上传(表单方式)#

在视频分享等应用中,用户上传文件时通常需要查看实时进度。为此,可使用 UploadFile 扩展方法,该方法支持实时进度获取,并允许对文件类型和大小进行限制。

以下示例展示了如何打印上传进度:

cs
await httpRemoteService.UploadFileAsync("https://localhost:7044/HttpRemote/AddFile", @"C:\Workspaces\httptest.jpg", "file"    , async progress =>    {        Console.WriteLine(await progress.ToSummaryStringAsync());  // 输出简要进度信息    });

控制台输出示例:

bash
Transferred 0.01MB of 0.01MB (100.00% complete, Speed: 0.86MB/s, Time: 0.01s, ETA: 0.00s), File: httptest.jpg, Path: C:\Workspaces\httptest.jpg.

若需在控制台中实时显示文件上传进度,推荐使用 UpdateConsoleProgressAsync() 方法。示例如下:

cs
await httpRemoteService.UploadFileAsync("https://localhost:7044/HttpRemote/AddFile", @"C:\Workspaces\httptest.jpg", "file"    , progress => progress.UpdateConsoleProgressAsync()); // 在控制台中更新文件传输进度条// ✅ 或使用 UploadFileWithConsoleProgressAsync 方法(带控制台进度打印)await httpRemoteService.UploadFileWithConsoleProgressAsync("https://localhost:7044/HttpRemote/AddFile", @"C:\Workspaces\httptest.jpg", "file");

执行后,控制台将显示如下进度信息:

bash
File: httptest.jpg, Path: C:\Workspaces\httptest.jpg.[##################################################] 61.35% (0.01MB/0.01MB) Speed: 0.86MB/s, Time: 0.01s, ETA: 0.00s.

若需限制文件类型和大小,可如下操作:

cs
await httpRemoteService.SendAsync(HttpRequestBuilder.UploadFile("https://localhost:7044/HttpRemote/AddFile", @"C:\Workspaces\httptest.jpg", "file"    , async progress =>    {        Console.WriteLine(await progress.ToSummaryStringAsync());  // 输出简要进度信息    })    .SetAllowedFileExtensions(".jpg;.png")  // 仅允许 jpg 和 png 类型    .SetMaxFileSizeInBytes(5 * 1024 * 1024));  // 限制文件大小为 5MB

若需在上传文件时附加额外的表单参数,可如下操作:

cs
await httpRemoteService.SendAsync(HttpRequestBuilder.UploadFile("https://localhost:7044/HttpRemote/AddFile", @"C:\Workspaces\httptest.jpg", "file"    , async progress =>    {        Console.WriteLine(await progress.ToSummaryStringAsync());  // 输出简要进度信息    })    .WithMultipart(multipart =>    {        multipart.AddText("Furion", "name");    });

通过上述方式,可以灵活满足各类文件上传需求。

HttpFileUploadBuilder 构建器#

除了上述方法,您还可以使用 HttpFileUploadBuilder 构建器来配置上传文件资源所需的各项设置。

cs
await httpRemoteService.SendAsync(HttpRequestBuilder.UploadFile("https://localhost:7044/HttpRemote/AddFile", @"C:\Workspaces\httptest.jpg", "file");

HttpFileUploadBuilder 构建器是框架提供专门用来上传文件资源所需的各项设置。HttpFileUploadBuilder 的构造函数是私有的,因此无法直接使用 new 关键字进行实例化,不过,框架提供了 HttpRequestBuilder.UploadFile 的多个静态重载方法创建 HttpFileUploadBuilder 的实例。

cs
HttpRequestBuilder.UploadFile(httpMethod, requestUri, filePath, name, onProgressChanged, fileName, configure);HttpRequestBuilder.UploadFile(requestUri, filePath, name, onProgressChanged, fileName, configure); // 默认 POST 请求

此外,HttpFileUploadBuilder 包含以下配置功能:

cs
// 默认为 POST 请求,默认表单名为 fileHttpRequestBuilder.UploadFile("https://localhost:7044/HttpRemote/AddFile", @"C:\Workspaces\httptest.jpg", "file")    // 设置内容类型(文件类型)    .SetContentType("image/jpeg")    // 设置允许的文件扩展名    .SetAllowedFileExtensions([".jpg", ".png"])    .SetAllowedFileExtensions(".jpg;.png")    // 设置允许的文件大小,字节单位    .SetMaxFileSizeInBytes(5 * 1024 * 1024)    // 设置文件传输进度(通知)的间隔时间    .SetProgressInterval(TimeSpan.FromSeconds(1))    // 设置在文件开始传输时的操作    .SetOnTransferStarted(() => {})    // 设置用于传输进度发生变化时执行的委托    .SetOnProgressChanged(async progress => { })    // 设置在文件传输完成时的操作,委托参数为文件传输总花费时间(毫秒)    .SetOnTransferCompleted(duration => {})    // 设置在文件传输发生异常时的操作    .SetOnTransferFailed(exception => {})    // 设置 HTTP 文件传输事件处理程序,CustomFileTransferEventHandler 为实现 IHttpFileTransferEventHandler 接口的类型    .SetEventHandler<CustomFileTransferEventHandler>()    .SetEventHandler(typeof(CustomFileTransferEventHandler))    // 追加多部分表单内容    .WithMultipart(multipart => {});    // 设置 HttpRequestBuilder 实例    .With(builder => {});   // 支持扩展更多

在通过 HttpRequestBuilder.UploadFile 方法成功构建 HttpFileUploadBuilder 实例后,您可以利用 Send 方法或异步的 SendAsync 方法来执行发送操作。

cs
httpRemoteService.Send(httpFileUploadBuilder, cancellationToken);await httpRemoteService.SendAsync(httpFileUploadBuilder, cancellationToken);

文件传输事件处理程序#

IHttpFileTransferEventHandler 接口允许您定义下载或上传文件的预处理操作。通过实现该接口,您可以创建自定义的文件传输事件处理程序,例如 CustomFileTransferEventHandler 类:

cs
public class CustomFileTransferEventHandler : IHttpFileTransferEventHandler{    // 在文件开始传输时的操作    public void OnTransferStarted() {}    // 传输进度发生变化时的操作    public Task OnProgressChangedAsync(FileTransferProgress fileTransferProgress) {}    // 在文件传输完成时的操作    public void OnTransferCompleted(long duration) {}    // 在文件传输发生异常时的操作    public void OnTransferFailed(Exception exception) {}}

要在应用程序中启用此处理程序,请在 Startup.csProgram.cs 文件中注册 CustomFileTransferEventHandler 服务:

cs
services.TryAddSingleton<CustomFileTransferEventHandler>();

接下来,您可以在构建 HTTP 请求时指定此处理程序:

cs
HttpRequestBuilder.UploadFile("https://localhost:7044/HttpRemote/AddFile", @"C:\Workspaces\httptest.jpg", "file")    .SetEventHandler<CustomFileTransferEventHandler>();HttpRequestBuilder.UploadFile("https://localhost:7044/HttpRemote/AddFile", @"C:\Workspaces\httptest.jpg", "file")    .SetEventHandler(typeof(CustomFileTransferEventHandler));    // 使用类型方式设置