WebClient.CancelAsync — File still downloading

梦想与她 提交于 2019-12-05 11:56:36

I was able to replicate what you saw: CancelAsync does not actually cancel the download.

Using HttpClient, you can get the stream and save it to a file using CopyToAsync, accepts a CancellationToken. Cancelling the token stops the download immediately.

Here is the DownloadService class that I modified to use HttpClient.

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();
        }
    }

This uses a Download class that looks like this:

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();
    }
}

You will still have some work to do to remove successfully-completed downloads from your Downloads list, but I'll leave that with you.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!