• 【WP8.1】HttpClient网络请求、进度以及终止


    工作这么长时间,起初还是喜欢用面向程序过程的思路去写代码。

    慢慢的才会用面向对象的思路分析、解决问题。也算是一点点进步吧。

    最近在做一个下载音乐的功能。用到了HttpClient类。

    于是就简单的写了一个文件处理类。主要实现了Get请求,Post还很不完善(Post看到过别人写的很不错的类,以后会贴出)。

    还有能够实时的显示下载进度,中断下载。

    贴出代码,在代码里解释:

        public class HttpRequest
        {
            #region Instance Field
    
            private readonly string _url;  //请求的url  
            private readonly string _body;  //Post/Get时的数据
            private HttpClient _httpClient;  
            private CancellationTokenSource _cts;  //用于取消请求
            private IProgress<HttpProgress> _httpProgressDownload;  //用于下载进度
            private IProgress<HttpProgress> _httpProgressUpload;
            private double progressUpload = 0;
            private double progressDownload = 0;  //下载进度
    
            #endregion
            
            #region Delegates
         
            public delegate void OnFailedEventHandle(string error, WebExceptionStatus status);
            public delegate void OnSucceedEventHandle(InMemoryRandomAccessStream randomAccessStream);
            public delegate void OnCancelEventHandle(string message);
            public delegate void OnProgressChangedEventHandle(double progress);
    
            #endregion
    
            #region Events
         //事件  分别用来处理获取失败、成功、取消、进度信息
            public event OnFailedEventHandle FailedEvent;
            public event OnSucceedEventHandle SucceedEvent;
            public event OnCancelEventHandle CancelEvent;
            public event OnProgressChangedEventHandle ProgressChangedEvent;
    
            #endregion
          //构造函数
            public HttpRequest(string url, string body = null)
            {
                this._url = url;
                this._body = body;
                _httpClient = new HttpClient();
                _cts = new CancellationTokenSource();
            }
         //开始运行 
    public void Run() { DoHttpClientRequest(); }      public async void DoHttpClientRequest() {
           //根据是否存在body判断是Get请求还是Post请求 RequestType method
    = string.IsNullOrEmpty(_body) ? RequestType.Get : RequestType.Post; var request = CreateHttp(_url, method); if (_httpClient != null) { try { HttpResponseMessage response = null; if (method == RequestType.Post) { //POST //_httpProgressUpload = new Progress<HttpProcess>(ProgressUploadHandler); //response = await _httpClient.SendRequestAsync(request).AsTask(_cts.Token, _progressUpload); response = await _httpClient.SendRequestAsync(request).AsTask(_cts.Token); } else if (method == RequestType.Get) { //GET
                  //下载进度状态信息 _httpProgressDownload = new Progress<HttpProgress>(ProgressDownloadHandler);  try { response = await _httpClient.SendRequestAsync(request).AsTask(_cts.Token, _httpProgressDownload); //HttpCompletionOption.ResponseHeadersRead多了这个参数    在接受到头之后完成。  于是就不继续进行了
                               //response = await _httpClient.SendRequestAsync(request, HttpCompletionOption.ResponseHeadersRead).AsTask(_cts.Token, _httpProgressDownload);

                     _cts.Token.ThrowIfCancellationRequested();                 
                     //处理流
    using (Stream responseStream = (await response.Content.ReadAsInputStreamAsync()).AsStreamForRead()) { //将Stream转换为IRandomAccessStream var randomAccessStream = new InMemoryRandomAccessStream(); var outputStream = randomAccessStream.GetOutputStreamAt(0); await RandomAccessStream.CopyAsync(responseStream.AsInputStream(), outputStream); if (randomAccessStream != null) { if (SucceedEvent != null) SucceedEvent(randomAccessStream); //获取到源的回调方法,并返回获取的内容 } } }
                   //中断Task时候会抛出异常,所以要通过try catch这种方法来获取是否终止。
    catch (TaskCanceledException) { //请求被取消 CancelEvent("下载已停止"); } } } catch (WebException e) { FailedEvent(e.Message, e.Status); } } } public HttpRequestMessage CreateHttp(string url, RequestType type = RequestType.Get) { HttpRequestMessage request = null; try { if (type == RequestType.Get) { request = new HttpRequestMessage(HttpMethod.Get, new Uri(url, UriKind.Absolute)); } else { request = new HttpRequestMessage(HttpMethod.Post, new Uri(url, UriKind.Absolute)); request.Content = SetPostContent(this._body); }
              SetHeaders();
    } catch (WebException e) { FailedEvent(e.Message, e.Status); } return request; }
         //Post请求内容
    public HttpStreamContent SetPostContent(string body) { byte[] subData = new byte[body.Length]; MemoryStream stream = new MemoryStream(subData); HttpStreamContent streamContent = new HttpStreamContent(stream.AsInputStream()); return streamContent; }
         public void SetHeaders()
            {
               
    //略
            }      public void ProgressDownloadHandler(HttpProgress progress) {
           //处理进度 包括了很多状态 如ConnectingToServerWaitingForResponse等
    string infoState = progress.Stage.ToString(); double totalByteToRecive = 0; if (progress.TotalBytesToSend.HasValue) { //要发送的数据 } if (progress.TotalBytesToReceive.HasValue) { //接收数据 获取总接收数据 totalByteToRecive = progress.TotalBytesToReceive.Value; } if (progress.Stage == HttpProgressStage.ReceivingContent) { progressUpload = progress.BytesReceived / totalByteToRecive; if (ProgressChangedEvent != null) { ProgressChangedEvent(progressUpload * 100); } } } public void Cancel() { if (_cts.Token.CanBeCanceled) {
              //取消请求并且释放资源 _cts.Cancel(); _cts.Dispose(); } } }    //枚举变量 来判断是Get请求还是Post请求
    public enum RequestType { Post, Get }

     后台代码:

     1        url = "http://mxd.766.com/sdo/music/data/1/m1.mp3"
     2        HttpRequest httpRequest = new HttpRequest(url);
     3 
     4             httpRequest.Run();
     5             httpRequest.SucceedEvent += async (result) =>
     6             {
     7                 try
     8                 {
     9                     await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    10                         {
    11                             //设置源
    12                             MediaControl.SetDownloadSource(result);
    13                         });
    14                 }
    15                 catch(Exception e)
    16                 {
    17                     
    18                 }
    19           //保存文件到音乐
    20                 IBuffer buffer = new Windows.Storage.Streams.Buffer((uint)result.Size);
    21                 await result.ReadAsync(buffer, (uint)result.Size, InputStreamOptions.None);
    22                 await StorageHelper.SaveToStorage(this.Classify.Name, selectItem.Name + ".mp3", buffer);
    23 
    24                 CommonHelper.ShowToast(selectItem.Name +  ".mp3 下载成功");
    25             };
    26             httpRequest.FailedEvent += async (ss, ee) =>
    27             {
    28                 await new MessageDialog("获取音乐失败").ShowAsync();
    29             };
    30             httpRequest.CancelEvent += async (ss1) =>
    31             {
    32                 await new MessageDialog(ss1).ShowAsync();
    33             };
    34             httpRequest.ProgressChangedEvent += (progress) =>
    35             {
    36                 selectItem.DownProgress = progress;
    37           //progress去绑定对象,就能够实时的显示进度
    38             };

    这样就能够实现下载、中断了。    我发现,在中断后再点击下载,进度条还是会接着走的。  

    这里并没有主动的去实现续传。


    注:HttpClient类发起的网络请求都是基于任务的异步方法,所以要取消其异步的操作可以通过异步任务的取消对象CancellationTokenSource对象来取消。

    如果使用CancellationTokenSource对象来取消异步的请求会触发TaskCanceledException异常,这个异常需要我们用try
    catch语句来捕获,便可以识别到请求是被取消的。

  • 相关阅读:
    mysql聚合函数
    轮播图与定时器
    3.23 参数 DOM 鼠标点击跟移入事件
    循环+数组
    for循环
    JS讲解跟遇到的问题
    CSS标签和属性回顾,JS初步了解
    2018.03.14理工大网站问题及解决办法
    2018.3.13 浮动 定位
    2018.3.12CSS样式
  • 原文地址:https://www.cnblogs.com/yffswyf/p/4718662.html
Copyright © 2020-2023  润新知