Http文件断点下载(Http请求头的Range字段)

所谓断点下载,也就是要从文件已经下载的地方开始继续下载。
在以前版本的 HTTP 协议是不支持断点的,HTTP/1.1 开始就支持了。一般断点下载时要用到 Range 。

Range 字段

请求头(Request Header)中,指定第一个字节的位置和最后一个字节的位置。用于告诉服务器自己想取对象的哪部分,一般格式:

Range: bytes=[first byte pos]-[last byte pos] 

例如:

Range: bytes=1173546-

或者

Range: bytes=1173546-2173546

例:请求下载整个文件:

Request Header

GET /test.rar HTTP/1.1 
Connection: close 
Host: 116.1.219.219
//一般请求下载整个文件是bytes=0- 
//或不用这个头,一般正常回应 
Range: bytes=0-801 

Range只是用来支持下载的,因为本地客户端在发起请求的时候能够通过文件的大小判断自己下到哪了;但是上传是不行的,即使客户端有记录进度,也不代表这些数据真的到了服务器,所以上传是用的切块,下载是用的range续传

举个例子:

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用OkHttp实现文件下载的示例代码,其中包括断点下载和暂停下载的功能: ```java public class DownloadManager { private static final String TAG = "DownloadManager"; private static final int DEFAULT_TIMEOUT = 10; private static DownloadManager mInstance; private OkHttpClient mOkHttpClient; private Handler mHandler; private DownloadManager() { mOkHttpClient = new OkHttpClient.Builder() .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS) .build(); mHandler = new Handler(Looper.getMainLooper()); } public static DownloadManager getInstance() { if (mInstance == null) { synchronized (DownloadManager.class) { if (mInstance == null) { mInstance = new DownloadManager(); } } } return mInstance; } public void download(final String url, final String destFileDir, final DownloadListener listener) { final Request request = new Request.Builder() .url(url) .build(); final Call call = mOkHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { handleError(call, e, listener); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { handleResponse(response, destFileDir, listener); } else { handleError(call, new IOException("Unexpected code " + response), listener); } } }); } private void handleResponse(Response response, String destFileDir, DownloadListener listener) { InputStream is = null; byte[] buf = new byte[2048]; int len; FileOutputStream fos = null; try { is = response.body().byteStream(); final long total = response.body().contentLength(); File dir = new File(destFileDir); if (!dir.exists()) { dir.mkdirs(); } File file = new File(dir, getFileName(response)); fos = new FileOutputStream(file); long sum = 0; while ((len = is.read(buf)) != -1) { fos.write(buf, 0, len); sum += len; final long finalSum = sum; mHandler.post(new Runnable() { @Override public void run() { listener.onProgress(finalSum * 1.0f / total); } }); } fos.flush(); mHandler.post(new Runnable() { @Override public void run() { listener.onSuccess(); } }); } catch (Exception e) { handleError(response.request().call(), e, listener); } finally { try { if (is != null) is.close(); } catch (IOException e) { } try { if (fos != null) fos.close(); } catch (IOException e) { } } } private void handleError(final Call call, final Exception e, final DownloadListener listener) { mHandler.post(new Runnable() { @Override public void run() { listener.onFailure(e); } }); if (call != null) { call.cancel(); } } private String getFileName(Response response) { String fileName = ""; String disposition = response.header("Content-Disposition"); if (!TextUtils.isEmpty(disposition)) { int index = disposition.indexOf("filename="); if (index > 0) { fileName = disposition.substring(index + 10, disposition.length() - 1); } } if (TextUtils.isEmpty(fileName)) { fileName = System.currentTimeMillis() + ".apk"; } return fileName; } public interface DownloadListener { void onProgress(float progress); void onSuccess(); void onFailure(Exception e); } } ``` 使用示例: ```java DownloadManager.getInstance().download(url, destFileDir, new DownloadManager.DownloadListener() { @Override public void onProgress(float progress) { // 更新进度条 } @Override public void onSuccess() { // 下载成功 } @Override public void onFailure(Exception e) { // 下载失败 } }); ``` 暂停下载可以通过调用`Call.cancel()`方法实现,断点下载可以通过在请求添加`Range`字段实现。相关代码如下: ```java public void download(final String url, final String destFileDir, final DownloadListener listener) { final Request request = new Request.Builder() .url(url) .build(); final Call call = mOkHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { handleError(call, e, listener); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { handleResponse(response, destFileDir, listener); } else { handleError(call, new IOException("Unexpected code " + response), listener); } } }); } public void pause(Call call) { if (call != null) { call.cancel(); } } public void resume(final String url, final String destFileDir, final DownloadListener listener) { final File file = new File(destFileDir, getFileName(url)); final long currentLength = file.length(); final Request request = new Request.Builder() .url(url) .addHeader("RANGE", "bytes=" + currentLength + "-") .build(); final Call call = mOkHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { handleError(call, e, listener); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { handleResponse(response, file.getAbsolutePath(), listener); } else { handleError(call, new IOException("Unexpected code " + response), listener); } } }); } ``` 相关问题:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bjxiaxueliang

您的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值