首页
下载
文档
问答社区
视频
捐赠
源代码
AI 助理
赞助商
CRMEB
Apipost
腾讯云
微擎
禅道
51Talk
商业产品
Swoole AI 智能文档翻译器
Swoole-Compiler PHP 代码加密器
CRMEB 新零售社交电商系统
登录
注册
全部
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
发表新帖
超过1G大文件下载,sendfile 无法获取到 Content-Length
### 问题描述 超过1G大文件下载,sendfile 无法获取到 Content-Length ### Swoole版本,PHP版本,以及操作系统版本信息 4.4.16 ### 相关代码 ```php //下载文件 function download($request, $response, $postData) { print_r($request); $file_md5 = $request->get['n']; $res = sqlpdo::getinstance(DFS_DB)->select("select info from dfs where md5='$file_md5'"); if ($res == 0) { $response->end(json_encode('sql文件不存在', 320)); return; } $res = json_decode($res[0]['info']); $group = $res->group; //文件所在的服务器组 logCode::wlog('当前服务器:' . IMG_ROUTE['serverName']); $group_url = IMG_ROUTE['serverGroup'][$group] ?? '.'; logCode::wlog('当前服务器URL:' . $group_url); $file_type = ''; //文件后缀名 if ($group == IMG_ROUTE['serverName']) { $file_url = $group_url . '/' . $res->fileUrlName ?? 'false'; $file_type = explode('.', $res->fileUrlName)[1]; echo '文件后后缀名:' . $file_type . PHP_EOL; } else { $file_url = $group_url . '/file/download?n=' . $file_md5; } logCode::wlog('文件地址:' . $file_url); //查找是否为http请求 if (strpos($file_url, 'http') === false) { if (file_exists($file_url)) { $file_length = filesize($file_url); $start_byte = 0; $end_byte = $file_length; $range = $request->header['range'] ?? false; if ($range) { echo 'range:' . $range . PHP_EOL; $range_ls = explode('-', str_replace('=', '', strstr($range, '='))); print_r($range_ls); $start_byte = $range_ls[0]; $end_byte = $range_ls[1]; if (empty($end_byte)) { $end_byte = $file_length; } $response->status(206); $response->header("Content-Range", "bytes $start_byte-$end_byte/$file_length"); } //获取文件类型 $finfo = finfo_open(FILEINFO_MIME); $mimetype = finfo_file($finfo, $file_url); finfo_close($finfo); echo '文件类型:' . $mimetype . PHP_EOL; $response->header('Content-Type', 'application/octet-stream'); //请求范围的度量单位 $response->header("Accept-Ranges", "bytes"); //Content-Length是指定包含于请求或响应中数据的字节长度 $response->header("Content-Length", $file_length); $response->header("Accept-Length", $file_length); //用来告诉浏览器,文件是可以当做附件被下载,下载后的文件名称为$file_name该变量的值。 $response->header("Content-Disposition", "attachment; filename=" . $file_md5 . '.' . $file_type); $response->header('Last-Modified: ', gmdate('D, d M Y 01:01:01', filemtime($file_url)) . ' GMT'); $response->header('Etags: ', fileinode($file_url)); // $response->header("Accept-Encoding", 'identity'); echo "从 $start_byte 到 $end_byte" . PHP_EOL; $response->sendfile($file_url, $start_byte, ($end_byte - $start_byte)); // if ($file_length > (1024 * 1024 * 1000)) { // $read_buffer = 2048; // $handle = fopen($file_url, 'rb'); // //总的缓冲的字节数 // $sum_buffer = 0; // //只要没到文件尾,就一直读取 // while (!feof($handle) && $sum_buffer < $file_length) { // $response->write(fread($handle, $read_buffer)); // $sum_buffer += $read_buffer; // // } // echo '已发送大小:' . $sum_buffer . PHP_EOL; // //关闭句柄 // fclose($handle); // $response->end(); // } else { // $response->sendfile($file_url); // } } else { $response->end('文件不存在'); } } else { $response->redirect($file_url); } } ``` ### 你期待的结果是什么?实际看到的错误信息又是什么? 为什么小于1G就是正常的,已经严格遵守 range协议
发布于4年前 · 3 次浏览 · 来自
提问
万物智联-1
### 问题描述 超过1G大文件下载,sendfile 无法获取到 Content-Length ### Swoole版本,PHP版本,以及操作系统版本信息 4.4.16 ### 相关代码 ```php //下载文件 function download($request, $response, $postData) { print_r($request); $file_md5 = $request->get['n']; $res = sqlpdo::getinstance(DFS_DB)->select("select info from dfs where md5='$file_md5'"); if ($res == 0) { $response->end(json_encode('sql文件不存在', 320)); return; } $res = json_decode($res[0]['info']); $group = $res->group; //文件所在的服务器组 logCode::wlog('当前服务器:' . IMG_ROUTE['serverName']); $group_url = IMG_ROUTE['serverGroup'][$group] ?? '.'; logCode::wlog('当前服务器URL:' . $group_url); $file_type = ''; //文件后缀名 if ($group == IMG_ROUTE['serverName']) { $file_url = $group_url . '/' . $res->fileUrlName ?? 'false'; $file_type = explode('.', $res->fileUrlName)[1]; echo '文件后后缀名:' . $file_type . PHP_EOL; } else { $file_url = $group_url . '/file/download?n=' . $file_md5; } logCode::wlog('文件地址:' . $file_url); //查找是否为http请求 if (strpos($file_url, 'http') === false) { if (file_exists($file_url)) { $file_length = filesize($file_url); $start_byte = 0; $end_byte = $file_length; $range = $request->header['range'] ?? false; if ($range) { echo 'range:' . $range . PHP_EOL; $range_ls = explode('-', str_replace('=', '', strstr($range, '='))); print_r($range_ls); $start_byte = $range_ls[0]; $end_byte = $range_ls[1]; if (empty($end_byte)) { $end_byte = $file_length; } $response->status(206); $response->header("Content-Range", "bytes $start_byte-$end_byte/$file_length"); } //获取文件类型 $finfo = finfo_open(FILEINFO_MIME); $mimetype = finfo_file($finfo, $file_url); finfo_close($finfo); echo '文件类型:' . $mimetype . PHP_EOL; $response->header('Content-Type', 'application/octet-stream'); //请求范围的度量单位 $response->header("Accept-Ranges", "bytes"); //Content-Length是指定包含于请求或响应中数据的字节长度 $response->header("Content-Length", $file_length); $response->header("Accept-Length", $file_length); //用来告诉浏览器,文件是可以当做附件被下载,下载后的文件名称为$file_name该变量的值。 $response->header("Content-Disposition", "attachment; filename=" . $file_md5 . '.' . $file_type); $response->header('Last-Modified: ', gmdate('D, d M Y 01:01:01', filemtime($file_url)) . ' GMT'); $response->header('Etags: ', fileinode($file_url)); // $response->header("Accept-Encoding", 'identity'); echo "从 $start_byte 到 $end_byte" . PHP_EOL; $response->sendfile($file_url, $start_byte, ($end_byte - $start_byte)); // if ($file_length > (1024 * 1024 * 1000)) { // $read_buffer = 2048; // $handle = fopen($file_url, 'rb'); // //总的缓冲的字节数 // $sum_buffer = 0; // //只要没到文件尾,就一直读取 // while (!feof($handle) && $sum_buffer < $file_length) { // $response->write(fread($handle, $read_buffer)); // $sum_buffer += $read_buffer; // // } // echo '已发送大小:' . $sum_buffer . PHP_EOL; // //关闭句柄 // fclose($handle); // $response->end(); // } else { // $response->sendfile($file_url); // } } else { $response->end('文件不存在'); } } else { $response->redirect($file_url); } } ``` ### 你期待的结果是什么?实际看到的错误信息又是什么? 为什么小于1G就是正常的,已经严格遵守 range协议
赞
0
分享
收藏
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
评论
2020-05-26
郭新华
bug了,int类型溢出了,下个小版本修复
赞
1
回复
2020-05-27
万物智联-1
回复
郭新华
非常感谢
赞
0
回复
2020-05-26
万物智联-1
![](/storage/article-column/ZknTqgTH6vJjbaXglnnjh3SDllquXLH7LVFgE0HM.png) 补充一下下载请求截图,用sendfile发送的文件,Content-lengtn是负数
赞
0
回复
微信公众号
热门内容
暂无回复的问答
- CodeGalaxy K3s 轻量集群节点之间如何实现负载均衡
- 关于openssl CURL WARNING swSSL_connect: SSL_connect(fd=69) failed. Error: error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small[1|394]
- 多个模型如何进行事务异常回退?
- websocket开启wss报错
- 协程tcp服务器如何使用多进程?recv()方法接收信息,打印出来的pid一直是同一个。没用使用到多进程啊。