[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)
        {       //处理进度  包括了很多状态 如ConnectingToServer、WaitingForResponse等
            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语句来捕获,便可以识别到请求是被取消的。

时间: 2024-09-07 06:09:59

[WP8.1]HttpClient网络请求、进度以及终止的相关文章

[深入浅出WP8.1(Runtime)]网络编程之HttpClient类

12.2 网络编程之HttpClient类 除了可以使用HttpWebRequest类来实现HTTP网络请求之外,我们还可以使用HttpClient类来实现.对于基本的请求操作,HttpClient类提供了一个简单的接口来处理最常见的任务,并为身份验证提供了适用于大多数方案的合理的默认设置.对于较为复杂的 HTTP 操作,更多的功能包括:执行常见操作(DELETE.GET.PUT 和 POST)的方法:获取.设置和删除 Cookie 的功能:支持常见的身份验证设置和模式:异步方法上提供的 HTT

【黑马Android】(06)使用HttpClient方式请求网络/网易新闻案例

使用HttpClient方式请求网络 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"

Android开发之网络请求通信专题(二):基于HttpClient的文件上传下载

上一篇专题Android开发之网络请求通信专题(一):基于HttpURLConnection的请求通信我们讲解了如何使用httpurlconnection来实现基本的文本数据传输.一般在实际开发中我们可以用于传输xml或者json格式的数据.今天我们来讲解另外一种http网络请求的方式:httpclient,并实现文件的上传和下载. 在这里插个题外话,其实这些网络请求有很多第三方jar包可以使用,这些包都封装得很好了.如果只是想使用,我们就直接拿别人得jar包来用就好.博主这里推荐一个叫xuti

赠送 HttpClient 和HttpURLConnection 的轻型网络 --》线程池介绍和网络请求流程

转载注明出处 :http://blog.csdn.net/codingandroid/article/details/41748743 作为一个框架,肯定要去处理一些比较复杂的情况,正常情况下当然不会阻塞,当情况比较复杂的时候,会出现前多个网络请求的情况,那对于这种情况我们规范去管理当然是最好的了,于是我们需要一个线程池. 首先解释一下,什么叫线程池  : 每当启动一个线程的时候,我们通常代码是   new Thead(){}.start();  new 一个对象 里面又要new一个runnab

OkHttpUtils一个专注于让网络请求更简单的框架

1.支持的常用功能 一般的 get,post,put,delete,head,options请求 基于Post的大文本数据上传,postString(),postJson()等 多文件和多参数统一的表单上传(允许监听上传进度) 支持一个key上传一个文件,也可以一个Key上传多个文件 大文件下载和下载进度回调 大文件上传和上传进度回调 支持cookie的内存存储和持久化存储,支持传递自定义cookie 提供网络缓存功能,默认支持304缓存协议,并额外扩展了三种本地缓存模式 支持301.302重定

常见网络请求库汇总

概述: 所有网络库的原理是: 网络请求一般是基于HttpURLConnection和HttpClient进行封装的,也有自己编写Socket实现的,比如ion和OkHttp:请求的执行一般是通过线程池来管理,异步请求得到结果,则通过回调接口接收:并且一般接收结果的回调都通过Handler去在主线程执行 几大网络请求库: Ion:Android Asynchronous Networking and Image Loading Volley:谷歌官方推出的网络请求和图片加载库 Retrofit:S

XDroidRequest网络请求框架,新开源

XDroidRequest 是一款网络请求框架,它的功能也许会适合你.这是本项目的第三版了,前两版由于扩展性问题一直不满意,思考来 思考去还是觉得Google的Volley的扩展性最强,于是借鉴了Volley的责任链模式,所以有了这个第三版. Provide 1 适配 Android 6.0 ,不再使用HttpClient相关API 2 一行代码发送请求,提供多种回调函数供选择, 3 支持8种网络请求方式 GET,POST,PUT,DELETE,HEAD,OPTIONS,TRACE,PATCH

android基于开源网络框架asychhttpclient,二次封装为通用网络请求组件

网络请求是全部App都不可缺少的功能,假设每次开发都重写一次网络请求或者将曾经的代码拷贝到新的App中,不是非常合理,出于此目的,我希望将整个网络请求框架独立出来,与业务逻辑分隔开,这样就能够避免每次都要又一次编写网络请求,于是基于我比較熟悉的asynchttpclient又一次二次封装了一个网络请求框架. 思路:网络请求层唯一的功能就是发送请求,接收响应数据,请求取消,cookie处理这几个功能,二次助封装后这些功能能够直接调用封装好的方法就可以. 二次助封装代码例如以下: 1.功能接口: /

(转载)Android之三种网络请求解析数据(最佳案例)

[置顶] Android之三种网络请求解析数据(最佳案例) 2016-07-25 18:02 4725人阅读 评论(0) 收藏 举报  分类: Gson.Gson解析(1)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 小武:相信大家都用过网络请求解析数据,只是方法不一样而已,但是,逻辑都是差不多的: 一:AsyncTask解析数据 AsyncTask主要用来更新UI线程,比较耗时的操作可以在AsyncTask中使用. AsyncTask是个抽象类,使用时需要继承这个