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

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

最近在做一个下载音乐的功能。用到了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 = ;
private double progressDownload = ;  //下载进度 #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();
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 = ;
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 * );
}
}
} public void Cancel()
{
if (_cts.Token.CanBeCanceled)
{
          //取消请求并且释放资源
_cts.Cancel();
_cts.Dispose();
}
}
}
   //枚举变量 来判断是Get请求还是Post请求
public enum RequestType
{
Post,
Get
}

后台代码:

        url = "http://mxd.766.com/sdo/music/data/1/m1.mp3"
       HttpRequest httpRequest = new HttpRequest(url); httpRequest.Run();
httpRequest.SucceedEvent += async (result) =>
{
try
{
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
//设置源
MediaControl.SetDownloadSource(result);
});
}
catch(Exception e)
{ }
          //保存文件到音乐
IBuffer buffer = new Windows.Storage.Streams.Buffer((uint)result.Size);
await result.ReadAsync(buffer, (uint)result.Size, InputStreamOptions.None);
await StorageHelper.SaveToStorage(this.Classify.Name, selectItem.Name + ".mp3", buffer); CommonHelper.ShowToast(selectItem.Name + ".mp3 下载成功");
};
httpRequest.FailedEvent += async (ss, ee) =>
{
await new MessageDialog("获取音乐失败").ShowAsync();
};
httpRequest.CancelEvent += async (ss1) =>
{
await new MessageDialog(ss1).ShowAsync();
};
httpRequest.ProgressChangedEvent += (progress) =>
{
selectItem.DownProgress = progress;
          //progress去绑定对象,就能够实时的显示进度
};

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

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

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

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

【WP8.1】HttpClient网络请求、进度以及终止的更多相关文章

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

    12.2 网络编程之HttpClient类 除了可以使用HttpWebRequest类来实现HTTP网络请求之外,我们还可以使用HttpClient类来实现.对于基本的请求操作,HttpClient类 ...

  2. Flutter -------- 网络请求之HttpClient

    今天来说说Flutter中的网络请求,HttpClient网络请求,包含get,post get var data; _get() async { Map newTitle; var response ...

  3. android4.0 HttpClient 以后不能在主线程发起网络请求

    android4.0以后不能在主线程发起网络请求,该异步网络请求. new Thread(new Runnable() { @Override public void run() { // TODO ...

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

    AsyncTask解析数据 AsyncTask主要用来更新UI线程,比较耗时的操作可以在AsyncTask中使用. AsyncTask是个抽象类,使用时需要继承这个类,然后调用execute()方法. ...

  5. iOS - Alamofire 网络请求

    前言 Alamofire 是 Swift 语言的 HTTP 网络开发工具包,相当于 Swift 实现 AFNetworking 版本.当然,AFNetworking 非常稳定,在 Mac OSX 与 ...

  6. Swift基础之使用Alamofire库进行网络请求和断点下载

    好久没有写过Swift相关的文章博客了,这里我就展示一下关于使用Alamofire库的方法 1.什么是Alamofire (1)Alamofire 的前身是 AFNetworking.AFNetwor ...

  7. ASI与AFN网络请求的的比较

    对比 ASI AFN 更新状态 2012年10月份,已经停止更新 持续更新中,目前已更新至3.0版 介绍 ASI的直接操作对象ASIHTTPRequest,是一个实现了了NSCopying协议的NSO ...

  8. 网络请求及各类错误代码含义总结(包含AFN错误码大全)

    碰见一个很奇葩的问题, 某些手机在设置了不知什么后, 某些 APP 死活 HTTPS 请求失败, 例如以 UMeng 统计HTTP 请求失败为例, Log如下: UMLOG: (Error   App ...

  9. XDroidRequest网络请求框架,新开源

    XDroidRequest 是一款网络请求框架,它的功能也许会适合你.这是本项目的第三版了,前两版由于扩展性问题一直不满意,思考来 思考去还是觉得Google的Volley的扩展性最强,于是借鉴了Vo ...

随机推荐

  1. Elasticsearch 调优 (官方文档How To)

    How To Elasticsearch默认是提供了一个非常简单的即开即用体验.用户无需修改什么配置就可以直接使用全文检索.结果高亮.聚合.索引功能. 但是想在项目中使用高性能的Elasticsear ...

  2. 【Linux】AWK入门

    什么是AWK AWK是一种用于处理文本的编程语言工具,一个模式匹配程序.一个典型的示例是将数据转换成格式化的报告. 在命令行输入如下awk命令: awk -F":" '{ prin ...

  3. js 页面无滚动条添加滚轮事件

    当页面无滚动条时,滑动滚轮时window.onscroll事件不会相应,此时应该去添加滚轮事件 var MouseWheelHandler=function(e){ e.preventDefault( ...

  4. [LeetCode] Range Sum Query - Immutable 区域和检索 - 不可变

    Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive ...

  5. [LeetCode] Remove Duplicates from Sorted Array II 有序数组中去除重复项之二

    Follow up for "Remove Duplicates":What if duplicates are allowed at most twice? For exampl ...

  6. 文件上传之——用SWF插件实现文件异步上传和头像截取

    之前写过几篇文件上传,那些都不错.今天小编带领大家体会一种新的上传方法,及使用Flash插件实现文件上传. 使用Flash的好处就是可以解决浏览器兼容性问题.之前我写的一个快捷复制功能也是利用的Fla ...

  7. IOS比较常用的第三方组件及应用源代码(持续更新中)

    把平时看到或项目用到的一些插件进行整理,文章后面分享一些不错的实例,若你有其它的插件欢迎分享,不断的进行更新~ 一:第三方插件 1:基于响应式编程思想的oc 地址:https://github.com ...

  8. Java NIO使用及原理分析(1-4)(转)

    转载的原文章也找不到!从以下博客中找到http://blog.csdn.net/wuxianglong/article/details/6604817 转载自:李会军•宁静致远 最近由于工作关系要做一 ...

  9. JAVA+Maven+TestNG搭建接口测试框架及实例

    1.配置JDK 见另一篇博客:http://www.cnblogs.com/testlurunxiu/p/5933912.html 2.安装Eclipse以及TestNG Eclipse下载地址:ht ...

  10. jquery.on()超级方法

    $.on()方法是jquery1.7之后的一个超级方法,将事件绑定和事件委托整合到一个函数中去,支持绑定多个事件,并且可以绑定自定义事件.使用起来很方便. demo传送门 事件委托 首先说一下事件委托 ...