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

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

最近在做一个下载音乐的功能。用到了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. 安装KVM及虚拟机

      创建lvm       安装kvm相关的包     需要安装的包                                                                 安 ...

  2. 快速排序算法 quick sort的理解

    最近做了一下算法的一些练习,感觉基础薄弱了,只是用一些已经有的东西来完成练习如quickSort(c++使用的时候是sort(起始位置,终止位置,比较函数),这个需要加头文件),但是不知道怎么推出来, ...

  3. Batis-iBatis基本操作(增删改查)

    Batis-iBatis基本操作(增删改查) 时间 2014-04-10 17:55:20  CSDN博客 原文  http://blog.csdn.net/mazhaojuan/article/de ...

  4. firefox 使用svg的image标签无法显示图片

    在image标签上添加 height.width(不要用css属性) href属性前面加xlink: (Mozilla自己的MDN都说不加xlink了,搞鸡巴)

  5. 20145213《信息安全系统设计基础》实验一 Linux开发环境的配置

    北京电子科技学院(BESTI) 实 验 报 告 课程:信息安全系统设计基础 班级:1452 姓名: 黄亚奇 祁玮 学号:20145213 20145222 成绩: 指导教师:娄嘉鹏 实验日期:2016 ...

  6. css的字体

    移动端使用的字体:http://www.cnblogs.com/PeunZhang/p/3592096.html

  7. poj 1251 Jungle Roads (最小生成树)

    poj   1251  Jungle Roads  (最小生成树) Link: http://poj.org/problem?id=1251 Jungle Roads Time Limit: 1000 ...

  8. WebAPI中无法获取Session对象的解决办法

    在MVC的WebApi中默认是没有开启Session会话支持的.需要在Global中重写Init方法来指定会话需要支持的类型 public override void Init() { PostAut ...

  9. 用 ElementTree 在 Python 中解析 XML

    用 ElementTree 在 Python 中解析 XML 原文: http://eli.thegreenplace.net/2012/03/15/processing-xml-in-python- ...

  10. MySQL种种

    mysql中You can't specify target table for update in FROM clause错误--http://blog.csdn.net/priestmoon/ar ...