如果我们的网站提供文件下载的服务,那么通常我们都希望下载可以断点续传(Resumable Download),也就是说用户可以暂停下载,并在未来的某个时间从暂停处继续下载,而不必重新下载整个文件。

通常情况下,Web服务器(如Apache)会默认开启对断点续传的支持。因此,如果直接通过Web服务器来提供文件的下载,可以不必做特别的配置,即可享受到断点续传的好处。由于这些文件直接通过Web服务器来提供下载,后端脚本无法对这个下载过程进行控制。这对于仅提供公开、静态文件的网站来说不是问题,但对于需要提供私有、动态文件的网站来说,直接通过Web服务器来提供下载就无法满足需求了。这时,就需要在编写后台脚本程序时,加入对断点续传的支持。

本文将以PHP为例,简要介绍实现文件下载断点续传的方法。

原理

断点续传的原理还是比较直观的。

HTTP协议规定了如何传输某个资源的一部分,而不是全部。比如,有一个文件的大小是1000字节,浏览器可以只请求该文件的前300个字节,或者只请求第500到第1000个字节。通过这种方式,就可以不必在一次请求中传输某个资源的全部内容,而是发起多次请求,每次仅请求其中的一部分内容。等所有这些请求都返回之后,再把得到的内容一块一块的拼接起来得到完整的资源。

实现断点续传就是要利用HTTP协议的上述特性。当用户暂停下载的时候,浏览器会记录已经下载到什么位置,当用户在未来某一时间恢复下载时,就可以从上次暂停的位置继续下载,而不必从头开始。

实现

由于部分传输不是强制的,服务器可以支持也可以不支持,所以,我们需要在程序中告诉浏览器,它请求的资源是否支持部分传输。这可以通过设置HTTP的 Accept-Ranges 响应头信息来实现。PHP代码如下:

header('Accept-Ranges: bytes');

Accept-Ranges: bytes 告诉浏览器,该资源支持以字节为单位的部分传输。这个响应头需要附加在支持部分传输的所有资源上。

当接受到一个请求时,我们需要从浏览器的请求中提取浏览器具体是在请求资源的哪一个部分。这个信息是通过 Range 请求头来传递的。在PHP中,它被存储在$_SERVER['HTTP_RANGE']中。我们需要检查这个变量是否定义了,如果定义了,则使用该值,否则,就将range设为整个资源。

$range = "0-". ($content_length-1);

if(isset($_SERVER['HTTP_RANGE'])){

$range = $_SERVER['HTTP_RANGE'];

}

接下来,就需要分析 $range 的值,来决定返回资源的哪一部分内容。可能的取值示例:

100-200 // 第100到第200字节

500-    // 第500字节到文件末尾

-1000   // 最后的1000个字节

这里需要注意,得到一个Range之后,你需要对它的取值进行检验,包括:

1.开始位置非负

2.结束位置需要大于开始位置

3.开始位置需要小于文件长度减一 (因为这里的位置索引是从0开始的)

4.若结束位置大于文件长度减一,则需要把它的值设置为文件长度减一

如果Range的取值不合法,则需要终止程序并告知浏览器:

header('HTTP/1.1 416 Requested Range Not Satisfiable');

为了保持文章简洁,具体的校验代码这里就不提供了。下面假定你已经校验了Range的取值,并得到了 $start 和 $end 两个变量,分别表示开始位置和结束位置。

接下来要做的就是把文件的对应部分的内容发送给浏览器。不过要注意的是,这里涉及到需要发送多个HTTP响应头信息,具体如下:

header('HTTP/1.1 206 Partial Content');

header('Accept-Ranges: bytes');

header("Content-Range: bytes $start-$end/$filesize");

$length = $end - $start + 1;

header("Content-Length: $length");

/* 输出文件的指定部分 */

这里的$length需要注意一下,它的取值是本次传输的内容的长度,而不是整个文件的长度。另外需要注意的一点是,这里的HTTP状态码是206,不是200。

总结

文件下载的断点续传实际上是利用了HTTP协议中对传输部分文件的支持。而HTTP协议的这一特性不仅可以用于实现断点续传,客户端程序也可以利用它来实现多线程下载。

在实现断点续传的过程中,需要注意正确设置各种HTTP头信息。错误的头信息将导致用户下载到的文件损坏,无法使用。

php文件断点续传,PHP实现文件下载断点续传详解相关推荐

  1. android 7 apk 安装程序,Android安装apk文件并适配Android 7.0详解

    Android安装apk文件并适配Android 7.0详解 首先在AndroidManifest.xml文件,activity同级节点注册provider: android:name="a ...

  2. android apk安装过程,Android安装apk文件并适配Android 7.0详解

    Android安装apk文件并适配Android 7.0详解 首先在AndroidManifest.xml文件,activity同级节点注册provider: android:name="a ...

  3. 把java文件打包成.jar (jar命令详解)

    把java文件打包成.jar (jar命令详解) 先打开命令提示符(win2000或在运行框里执行cmd命令,win98为DOS提示符),输入jar Chelp,然后回车(如果你盘上已经有了jdk1. ...

  4. java中属性文件读取案例_java相关:Spring中属性文件properties的读取与使用详解

    java相关:Spring中属性文件properties的读取与使用详解 发布于 2020-6-3| 复制链接 摘记: Spring中属性文件properties的读取与使用详解实际项目中,通常将一些 ...

  5. c++中.dll与.lib文件的生成与使用的详解

    c++中.dll与.lib文件的生成与使用的详解 --------------------------------------------------------------------------- ...

  6. python中with open写csv文件_Python中的CSV文件使用with语句的方式详解

    是否可以直接使用with语句与CSV文件?能够做这样的事情似乎很自然: import csv with csv.reader(open("myfile.csv")) as read ...

  7. java 输入流可以合并吗_Java 使用IO流实现大文件的分割与合并实例详解

    java 使用IO流实现大文件的分割与合并 文件分割应该算一个比较实用的功能,举例子说明吧比如说:你有一个3G的文件要从一台电脑Copy到另一台电脑, 但是你的存储设备(比如SD卡)只有1G ,这个时 ...

  8. python读取大文件csv_对python中大文件的导入与导出方法详解

    1.csv文件的导入和导出 通过一个矩阵导出为csv文件,将csv文件导入为矩阵 将csv文件导入到一个矩阵中 import numpy my_matrix = numpy.loadtxt(open( ...

  9. 【运维】PowerShell编程 目录文件相关方法的封装与案例详解

    PowerShell 目录文件管理 目录文件相关方法的封装与案例详解 李俊才 的 CSDN 博客:https://blog.csdn.net/qq_28550263?type=blog 邮箱 :291 ...

  10. 文件包含漏洞—allow_url_fopen和allow_url_include详解

    文件包含漏洞_allow_url_fopen和allow_url_include详解 提要:在文件包含漏洞中,PHP脚本环境中php.ini文件中通常会涉及到这两个参数,两个参数的开启或关闭影响文件包 ...

最新文章

  1. 基于(Mixed)Integer Programming方法的服务组合相关论文实验介绍 (1)
  2. java bindview_手写 ButterKnife BindView
  3. Flink JAR包上传和运行逻辑
  4. .NET中的文件IO操作实例
  5. 这群理想主义者,在腾讯用10年做到了畅销榜第一
  6. 集成Springboot----ElasticSearch
  7. sql server 2005 (select查询语句用法)
  8. c语言借阅管理题目内容描述,C语言-图书借阅管理系统
  9. Excel突然出现很多小黑点
  10. 这几个好用的简单流程图模板,你可不能错过
  11. ACM 比赛如何正确开局、队员如何分工、如何把状态调整到最佳?
  12. (附源码)springboot闲置衣物捐赠系统 毕业设计 021009
  13. 雷达指标,应用,抗干扰技术——概述汇总
  14. 一文搞懂Nginx如何配置Http、Https、WS、WSS!
  15. html+div+动画效果,html+css3太阳系行星运转动画效果的实现代码
  16. 问题 A: 【二维数组】计算三阶行列式的值
  17. Numpy:关于flatten的理解
  18. IIS应用程序池自动回收
  19. 帝国cms 数据恢复mysql_帝国cms系统数据库恢复详细教程(图文)
  20. 《WCDMA空中接口技术》读书笔记7: R5 HSDPA技术

热门文章

  1. 使用javascript在客户端获取URL参数值的函数
  2. html5 input min,HTML Input Time min用法及代码示例
  3. Java Web-网页基础-HTML-URL
  4. wsdl可以访问单但是调不通_Dubbo 一些你不一定知道但是很好用的功能
  5. GaussDB(for MySQL) NDP与PQ测试体验
  6. Oracle标准审计实战过程详解
  7. 如何使用RMAN duplicate搭建12C的Data Guard环境?
  8. 一次900万+数据量的 SQL 查询优化分析【上百倍性能优化】
  9. DBA自述:非科班出身,如何成为Oracle ACE
  10. 缓存最关心的问题是什么