-
概述
网络编程中文件的上传下载是最常见的场景,本着不重复造轮子的原则,日常工作如果遇到相关问题我们首先想到的可能是从网上找现成的代码直接拿来用,很少去关心具体是如何实现的,可能也是没时间去研究别人如何实现。如果代码能够满足我们现阶段的要求,则万事大吉,但是如果使用代码的过程中出现意想不到的问题,我们解决起来可能会比较麻烦,因为代码不是我们自己写的,对代码不熟,不能快速的查找问题的原因。个人认为不重复造轮子的前提是你必须有能力造一个相同的轮子,这样在使用别人的代码时才能更加得心应手。
最近工作需要在Android里面实现文件的上传和下载功能,当然为了快速实现我也是从网上找了别人的代码直接拿来用了,期间也根据自己的需求做了适当的修改,现在就拿出来给大家分享一下。
- 原理分析
Android应用与服务进行交互一般是通过Http请求的方式进行,文件下载也同样通过Http请求,一般情况下我们通过请求一个文件的url地址,服务端返回一个文件流,我们通过读取文件流的方式将文件内容再以流的方式写到本地的文件中,这就是文件下载的基本过程。但是如果要下载的文件较大时我们一般需要采用分块下载(或叫做多线程下载)的方式,以减少下载过程中出现错误的可能性。之前我们一个http请求返回整个文件的文件流,现在我们需要分多次请求,每个请求返回的文件流只能读取文件的一部分。在客户端每次请求的时候需要携带关于块的信息,即本次请求是要下载文件的哪个部分,然后服务器通过解析只返回文件的一部分,然后客户端将每个请求的结果进行汇总,即进行文件的合并,最终得到一个完整的文件。
在http协议1.1中新增了一个Range头参数,这是目前实现多线程下载的核心所在。Range的使用方式为“Range: bytes=0-1”表示下载文件的前两个字节,即从0个字节到第1个字节,一共两个字节。接下来我们先看一下如何使用java实分块下载的功能。
- 代码实现
HttpURLConnection http = (HttpURLConnection) downUrl.openConnection(); // 开启HttpURLConnection连接 http.setConnectTimeout(5 * 1000); // 设置连接超时时间为5秒钟 http.setRequestMethod("GET"); // 设置请求的方法为GET http.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"); // 设置客户端可以接受的返回数据类型 http.setRequestProperty("Accept-Language", "zh-CN"); // 设置客户端使用的语言问中文 http.setRequestProperty("Referer", downUrl.toString()); // 设置请求的来源,便于对访问来源进行统计 http.setRequestProperty("Charset", "UTF-8"); // 设置通信编码为UTF-8 int startPos = block * (threadId - 1) + downloadedLength;// 开始位置 int endPos = block * threadId - 1;// 结束位置 http.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos);// 设置获取实体数据的范围,如果超过了实体数据的大小会自动返回实际的数据大小 http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"); // 客户端用户代理 http.setRequestProperty("Connection", "Keep-Alive"); // 使用长连接 http.setRequestProperty("Accept-Encoding", "gzip"); InputStream inStream = http.getInputStream(); // 获取远程连接的输入流
首先代码第一个行获取一个HttpURLConnection连接对象,然后设置连接的超时时为5s,请求方式为get方式,接收文件的类型,语言,请求的来源编码方式。代码第10行为关键代码设置请求头中的Range参数值,参数值的信息需要我们根据文件分块的大小,和当前线程请求的是第几块计算出一个范围。所有的请求参数设置完成之后我们通过调用getInputStream方法获取返回的文件流。这就是请求发送的实现,下面我们看一下文件流获取之后合并文件的实现。
Android实现基于http协议的文件下载
最新推荐文章于 2022-03-30 16:50:31 发布