【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 = ;
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网络请求、进度以及终止的更多相关文章
- [深入浅出WP8.1(Runtime)]网络编程之HttpClient类
12.2 网络编程之HttpClient类 除了可以使用HttpWebRequest类来实现HTTP网络请求之外,我们还可以使用HttpClient类来实现.对于基本的请求操作,HttpClient类 ...
- Flutter -------- 网络请求之HttpClient
今天来说说Flutter中的网络请求,HttpClient网络请求,包含get,post get var data; _get() async { Map newTitle; var response ...
- android4.0 HttpClient 以后不能在主线程发起网络请求
android4.0以后不能在主线程发起网络请求,该异步网络请求. new Thread(new Runnable() { @Override public void run() { // TODO ...
- Android之三种网络请求解析数据(最佳案例)
AsyncTask解析数据 AsyncTask主要用来更新UI线程,比较耗时的操作可以在AsyncTask中使用. AsyncTask是个抽象类,使用时需要继承这个类,然后调用execute()方法. ...
- iOS - Alamofire 网络请求
前言 Alamofire 是 Swift 语言的 HTTP 网络开发工具包,相当于 Swift 实现 AFNetworking 版本.当然,AFNetworking 非常稳定,在 Mac OSX 与 ...
- Swift基础之使用Alamofire库进行网络请求和断点下载
好久没有写过Swift相关的文章博客了,这里我就展示一下关于使用Alamofire库的方法 1.什么是Alamofire (1)Alamofire 的前身是 AFNetworking.AFNetwor ...
- ASI与AFN网络请求的的比较
对比 ASI AFN 更新状态 2012年10月份,已经停止更新 持续更新中,目前已更新至3.0版 介绍 ASI的直接操作对象ASIHTTPRequest,是一个实现了了NSCopying协议的NSO ...
- 网络请求及各类错误代码含义总结(包含AFN错误码大全)
碰见一个很奇葩的问题, 某些手机在设置了不知什么后, 某些 APP 死活 HTTPS 请求失败, 例如以 UMeng 统计HTTP 请求失败为例, Log如下: UMLOG: (Error App ...
- XDroidRequest网络请求框架,新开源
XDroidRequest 是一款网络请求框架,它的功能也许会适合你.这是本项目的第三版了,前两版由于扩展性问题一直不满意,思考来 思考去还是觉得Google的Volley的扩展性最强,于是借鉴了Vo ...
随机推荐
- Unity 重要基础知识点
这是两个月前的学习记录,发出来了下,如果有误欢迎大家指出: 脚本生命周期 //每当脚本被加载时调用一次 // 1. 在Awake中做一些初始化操作 void Awake(){ //初始化publi ...
- 必杀技———SQL基础整理系列(一)
SQL(Structured Query Language)——结构化查询语言 SQL语言的组成部分 数据定义语言 (DDL:Data Definition Language) 负责数据结构定义与数据 ...
- [LeetCode] Nth Digit 第N位
Find the nth digit of the infinite integer sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... Note: n i ...
- [LeetCode] Sqrt(x) 求平方根
Implement int sqrt(int x). Compute and return the square root of x. 这道题要求我们求平方根,我们能想到的方法就是算一个候选值的平方, ...
- 抱歉!15:44-16:39阿里云RDS故障造成全站不能正常访问
非常非常抱歉!2016年3月7日15:44-16:39,由于阿里云RDS(云数据库)故障,造成全站不能正常访问,给您带来了很大很大的麻烦,恳请您的谅解! 故障是在15:44开始出现的,应用日志中出现大 ...
- Codeforces #364 DIV2
~A题 A. Cards time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- How to Disable Strict SQL Mode in MySQL 5.7
If your app was written for older versions of MySQL and is not compatible with strict SQL mode in My ...
- 使用Eclipse进行远程调试
转自:http://blog.csdn.net/sunyujia/article/details/2614614 今天决定做件有意义的事,写篇图文并茂的blog,为什么要图文并茂?因为很多事可能用语言 ...
- 冰冻三尺非一日之寒--Django框架【进阶篇】
第十九章 Django进阶 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去 ...
- react native 图片样式导致的坑
最近项目中遇到一个问题,代码如下,点击进入另一个页面时需要显示的图片会黑屏,另外退回到该页面的时候下面代码中的第一个图片会全黑几秒才渲染,从另一个路径进入该页面时并没有此问题,就找了半天是不是数据的问 ...