当前位置: 首页 > 后端技术 > PHP

PHP下载文件、限速、X-sendfile

时间:2023-03-29 17:26:28 PHP

1、普通文件下载①laravel框架HTTP响应的下载方式$pathToFile='myfile.csv';//参数一:绝对路径$downloadName='downloadFile.csv';//参数二:下载的文件名//下载参数三:HTTP头信息returnresponse()->download($pathToFile,$downloadName);②PHP实现$pathToFile='myfile.csv';//绝对文件路径$downloadName='downloadFile.csv';//下载文件名//输入文件标签Header("Content-type:application/octet-stream");Header("Accept-Ranges:bytes");Header("Accept-Length:".filesize($pathToFile));Header("Content-Disposition:filename=".$downloadName);//输出文件内容$file=fopen($pathToFile,"r");echofread($file,filesize($pathToFile));fclose($文件);//或//读取文件($pathToFile);fread()和readfile()的区别可以参考https://segmentfault.com/q/10...但是有时候为了节省带宽,避免瞬时流量过大造成网络拥塞,需要考虑下载限速问题2.下载文件限速$pathToFile='myfile.csv';//文件的绝对路径$downloadName='downloadFile.csv';//下载的文件名$download_rate=30;//设置下载速率(30kb/s)if(file_exists($pathToFile)&&is_file($pathToFile)){header('Cache-control:private');//发送标头header('Content-Type:application/octet-stream');header('Content-Length:'.filesize($pathToFile));header('Content-Disposition:filename='.$downloadName);flush();//刷新内容$file=fopen($pathToFile,"r");while(!feof($file)){printfread($file,round($download_rate*1024));//将文件的当前部分发送到浏览器flush();//flush内容输出到browsersleep(1);//1秒后终端继续运行}fclose($file);//关闭文件流}else{abort(500,'file'.$pathToFile.'doesnotexist');}此时出现问题,当$download_rate>1kb时,文件下载正常;当$download_rate<1kb时,文件要等待一段时间才能下载,原因是buffer是一个内存地址空间,Linux系统默认大小一般是4096(1kb),也就是一个内存页.主要用于存储速度不同步的设备或不同优先级的设备之间存储数据。例如,当你打开一个文本编辑器编辑一个文件时,每输入一个字符,操作系统不会立即将该字符直接写入磁盘,而是先写入缓冲区,当一个缓冲区已满时才当缓冲区中的数据写入磁盘时。同理,执行echo和print时,并不是立即将输出通过tcp传递给客户端浏览器显示,而是将数据写入php缓冲区。php的output_buffering机制是指在tcpbuffer之前,建立一个新的queue,数据必须经过这个queue。当一个php缓冲区满时,脚本进程会将php缓冲区中的输出数据交给系统内核,通过tcp发送给浏览器显示。因此,数据会依次写入这些地方:echo/pring->phpbuffer->tcpbuffer->browser。资料:http://blog.csdn.net/superhos...未开启缓存时,脚本输出的内容在服务器端等待输出,flush()可以立即发送等待输出的内容给客户。启用缓存后,脚本输出的内容会存储在输出缓存中。此时没有内容等待输出。您不会直接使用flush()向客户端发送任何内容。ob_flush()的作用是将原来存放在输出缓存中的内容取出,设置为等待输出状态,但不会直接发送给客户端。这时候需要先用ob_flush(),再用flush()。end立即得到脚本的输出。而且这篇文章也介绍了ob_flush()和flush()的区别http://www.laruence.com/2010/...但是这个方法是通过一个固定的buffer从磁盘读取文件内容,循环读取内存,然后发送到前端web服务器,最后发送给用户。当要下载的文件较大时,这种方式会消耗大量内存,甚至会导致php进程超时或崩溃,这时使用X-Sendfile。3、X-SendfileX-Sendfile是一种将文件下载请求从后端应用程序传输到前端Web服务器进行处理的机制。可以消除后端程序读取文件和处理发送的压力,从而显着提高服务器效率。特别是在处理大文件下载时。我用的是nginx,所以apache请参考https://tn123.org/mod_xsendfile/①首先添加location/download/{internal;root/some/path;//absolutepath}在配置文件中表示该路径只能在Nginx内部访问,浏览器不能直接访问,防止非法下载。注意在location/{...}前面加上,这样在代码中使用时,文件路径可以写成“/download/myfile.csv”②重启Nginx,写代码$pathToFile='myfile.csvcsv';//文件绝对路径$downloadName='downloadFile.csv';//下载文件名$download_rate=30;//设置下载速率(30kb/s)if(file_exists($pathToFile)&&is_file($pathToFile)){return(newResponse())->withHeaders(['Content-Type'=>'application/octet-stream','Content-Disposition'=>'attachment;filename='.$downloadName,'X-Accel-Redirect'=>$pathToFile,//让Xsendfile发送文件'X-Sendfile'=>$pathToFile,'X-Accel-Limit-Rate'=>$download_rate,]);}else{abort(500,'file'.$pathToFile.'doesnotexist');}想了解更多X-sendfile的请自行查看,记得关注我

猜你喜欢