gpt4 book ai didi

c# - WebClient.CancelAsync — 文件仍在下载

转载 作者:太空狗 更新时间:2023-10-30 01:30:01 24 4
gpt4 key购买 nike

我正在尝试使用 Asp.NET Core 创建一个 Web API,它公开路由以开始和取消大文件的长时间下载。服务器应该能够同时处理多个下载。

  • 下载是使用 WebClient.DownloadFileAsync 执行的,以便获得较短的响应时间并返回 downloadId 供以后使用。 WebClient 的实例作为值存储在静态字典中,其对应的 key 自然是 downloadId
  • 应在通过访问与 downloadId 键对应的字典值检索到的客户端实例上使用 WebClient.CancelAsync 取消下载。

当下载完成且未被取消时,以下代码可以完美运行; AsyncCompletedEventHandler(OnDownloadFileCompleted 在这种情况下)被正确调用。

问题:调用WebClient.CancelAsync 时,文件继续下载,OnDownloadFileCompleted 不会立即调用。 WebClient 在调用处理程序之前似乎要等到下载完成。然而,在这两种情况下,属性 AsyncCompletedEventArgs.Canceled 都已正确设置(例如,如果确实调用了 WebClient.CancelAsync,则设置为 true

  • 我是不是漏掉了什么?
  • 是否有更好/更智能的模式来处理 WebAPI 中的多个下载?

非常感谢任何帮助!

下载Controller.cs

[Route ("api/download")]
public class DownloadController {

private readonly DownloadService service;

public DownloadController (DownloadService service) {
this.service = service;
}

[Route ("start")]
[HttpPost]
public string Start ([FromForm] string fileUrl) => this.service.StartDownload (fileUrl);

[Route ("cancel")]
[HttpPost]
public void Cancel ([FromForm] string downloadId) => this.service.CancelDownload (downloadId);
}

下载Service.cs

public class DownloadService {
public string DOWNLOAD_FOLDER { get => "C:\\tmp"; }
public static Dictionary<string, WebClient> DownloadClients = new Dictionary<string, WebClient> ();

public string StartDownload (string fileUrl) {
var downloadId = Guid.NewGuid ().ToString ("N");
DownloadClients[downloadId] = new WebClient ();
DownloadClients[downloadId].DownloadFileCompleted += OnDownloadFileCompleted;
DownloadClients[downloadId].DownloadFileAsync (new Uri (fileUrl), Path.Combine (DOWNLOAD_FOLDER, downloadId), downloadId);
return downloadId;
}

public void CancelDownload (string downloadId) {
if (DownloadClients.TryGetValue (downloadId, out WebClient client)) {
client.CancelAsync ();
}
}

private void OnDownloadFileCompleted (object sender, AsyncCompletedEventArgs e) {
var downloadId = e.UserState.ToString ();
if (!e.Cancelled) {
Debug.WriteLine ("Completed");
} else {
Debug.WriteLine ("Cancelled"); //will only be reached when the file finishes downloading
}

if (DownloadClients.ContainsKey (downloadId)) {
DownloadClients[downloadId].Dispose ();
DownloadClients.Remove (downloadId);
}
}
}

最佳答案

我能够复制您看到的内容:CancelAsync 实际上并没有取消下载。

使用 HttpClient,您可以使用 CopyToAsync 获取流并将其保存到文件,接受 CancellationToken。取消 token 会立即停止下载。

这是我修改为使用 HttpClientDownloadService 类。

public class DownloadService {
public string DOWNLOAD_FOLDER {
get => "C:\\tmp";
}

public static readonly ConcurrentDictionary<string, Download> Downloads = new ConcurrentDictionary<string, Download>();

public async Task<string> StartDownload(string fileUrl) {
var downloadId = Guid.NewGuid().ToString("N");
Downloads[downloadId] = new Download(fileUrl);
await Downloads[downloadId].Start(Path.Combine(DOWNLOAD_FOLDER, downloadId));

return downloadId;
}

public void CancelDownload(string downloadId) {
if (Downloads.TryRemove(downloadId, out var download)) {
download.Cancel();
}
}

这使用了如下所示的 Download 类:

public class Download {
private static readonly HttpClient Client = new HttpClient();
private readonly string _fileUrl;

private readonly CancellationTokenSource _tokenSource = new CancellationTokenSource();
private Task _copyTask;
private Stream _responseStream;
private Stream _fileStream;

public Download(string fileUrl) {
_fileUrl = fileUrl;
}

public async Task Start(string saveTo) {
var response = await Client.GetAsync(_fileUrl, HttpCompletionOption.ResponseHeadersRead);
_responseStream = await response.Content.ReadAsStreamAsync();
_fileStream = File.Create(saveTo);
_copyTask = _responseStream.CopyToAsync(_fileStream, 81920, _tokenSource.Token).ContinueWith(task => {
if (task.IsCanceled) return;
_responseStream.Dispose();
_fileStream.Dispose();
});
}

public void Cancel() {
_tokenSource.Cancel();
_responseStream.Dispose();
_fileStream.Dispose();
}
}

要从下载 列表中删除成功完成的下载,您还有一些工作要做,但我会把它留给您。

关于c# - WebClient.CancelAsync — 文件仍在下载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48187976/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com