zoukankan      html  css  js  c++  java
  • 【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语句来捕获,便可以识别到请求是被取消的。

  • 相关阅读:
    word设置的密码忘了怎么办?
    Navicat Report Viewer 设置 HTTP 的方法
    如何处理Navicat Report Viewer 报表
    excel密码忘记了怎么办
    Beyond Compare文本比较搜索功能详解
    Popular Cows POJ
    Problem B. Harvest of Apples HDU
    网络流模型整理
    The Shortest Statement CodeForces
    Vasya and Multisets CodeForces
  • 原文地址:https://www.cnblogs.com/yffswyf/p/4718662.html
Copyright © 2011-2022 走看看