百度网盘下载功能的后端实现-PHP

百度网盘下载功能的后端实现-PHP

主要阐述一下
1、超大文件如何下载才合理
2、实现分段下载
3、实现极速上传到我的网盘
4、实现下载限速

基本的文件下载原理:https://blog.csdn.net/raoxiaoya/article/details/100929744

文件下载我们一般是在后台下载excel用的比较多,文件不大,单次下载,基本的方式就能解决了,但是当我们要专门提供下载服务的时候,就应该多考虑一些。

文件:$file = ‘D:/software/ideaIU-2019.1.3.exe’;// 大小:561M

一、超大文件如何下载才合理
方法1:
使用readfile,它会将文件分块读取到输出缓冲区,如果缓冲区满了,自然就会响应到客户端,形成一种流式的文件传输。

<?php
header('Content-Disposition: attachment; filename="ideaIU-2019.1.3.exe"');

$file = 'D:/software/ideaIU-2019.1.3.exe';// 大小:561M
readfile($file);

方法2:
使用file_get_contents分块读取,输出
对于$file,我们无法一次性将其加入内存,然后输出到输出流,即使我们调整了内存大小可以加载,当多个请求同时来下载这个文件时也是不行的。所以需要分段加载进内存然后输出。
php输出缓冲区大小默认为4086Byte,也就是4kb,我们就一次读取4kb。输出缓冲区也是要等到满了之后或者程序执行结束才响应给web服务器的,因为这样可以较少网络IO次数。

<?php

header('Content-Disposition: attachment; filename="ideaIU-2019.1.3.exe"');
flush();

$file = 'D:/software/ideaIU-2019.1.3.exe';// 大小:561M
$buffer = '';
$len = 4096;// 4k
$step = 0;

do{
	$start = $step * $len;
	$buffer = file_get_contents($file, false, null, $start, $len);
    file_put_contents('php://output', $buffer);
    $step++;
}while($buffer);

flush()函数的作用是人为的将缓冲区的内容响应出去,这样做的好处是使用户体验更友好。假如我们要导出一个表格,我们要1、设置header,2、读数据库,运算得出结果,3、按照excel协议输出;如果计算复杂的话,用户要等待不少时间才能看到浏览器弹出下载,因为header的设置不足以把缓冲区填满,要等到步骤3的写入,所以这段时间内浏览器是接收不到任何响应的,因为浏览器是需要接收到header才能知道是一个下载任务,才知道弹出下载的,所以使用flush()方法可以提前让用户看到下载的提示,当然对于我们这种单纯下载的功能使不使用flush()效果不明显。

二、实现分段下载
百度云盘的下载会将你本次下载的进度保存起来,即使你重新登录了也不影响继续下载,这就是分段下载,实现起来也很简单,客户端需要保留上次下载到哪里了,再次下载的时候传参就好了。

<?php

header('Content-Disposition: attachment; filename="ideaIU-2019.1.3.exe"');
flush();

$file = 'D:/software/ideaIU-2019.1.3.exe';// 大小:561M
$buffer = '';
$len = 4096;// 4k
$step = 0;
$history = $_GET['history'] ?? 0;// 或者通过header传参

do{
    $start = $step * $len + $history;
	$buffer = file_get_contents($file, false, null, $start, $len);
    file_put_contents('php://output', $buffer);
    $step++;
}while($buffer);

三、实现极速上传到我的网盘
当我们点击别人的资源保存到我的网盘时,实际上保存的就是一个映射,一条记录,将这个文件的编码保存到我的名下,而删除的话删除的也是记录,而不是实体文件,实际上服务器上同一个文件只需要保存一份就可以了(当然会有备份)。
有时候我们从本地上传一个文件到网盘速度很快,一闪就好了,有时候却是要上传很久,这是为什么呢?
当我们在php官网下载php包的时候,每个包下面后有一个哈希编码,用以保证这个文件没有被篡改过,用户可以对这个文件使用哈希运算来对比哈希值。此处也是一样,只要你要上传的文件哈希值已经存在了,就可以判断你要上传的文件存在服务器上了,就不用再次上传了,只需要给你加个记录就好了,

四、实现下载限速
下载限速是一个很恶心的东西,它的实现也很简单。
假如要限制你的速度为100k/s,只需要控制在1秒的时间内只给你100k的数据,多了没有。
限速的前提是,原始的速度肯定大于这个速度,否则没有限制的必要了。

<?php

header('Content-Disposition: attachment; filename="ideaIU-2019.1.3.exe"');
flush();

$file = 'D:/software/ideaIU-2019.1.3.exe';// 大小:561M
$buffer = '';
$len = 102400;// 100k/s
$step = 0;
$history = $_GET['history'] ?? 0;// 或者通过header传参

do{
    $t1 = microtime(true);

    $start = $step * $len + $history;
    $buffer = file_get_contents($file, false, null, $start, $len);
    file_put_contents('php://output', $buffer);

    flush();// 做到精确控制,防止数据不够填满缓冲区

    $t2 = microtime(true);
    $t = intval((1 - ($t2 - $t1)) * 1000000);
    if($t > 0){
        usleep($t);
    }

    $step++;
}while($buffer);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值