读取用 php 分块的范围块

2024-05-08

我有一个输入字段,可以在其中粘贴下载网址。 之后,我使用 AJAX 请求来获取文件信息,例如 headerinfo、内容长度、mime 类型,如果我使用curl 接受范围。

然后,我开始连续循环 xhr2 请求,其中包含我的 php 文件的范围。

http://www.example.com/chunks.php?url=http://url.com/someFile.ext&range=0-1024
http://www.example.com/chunks.php?url=http://url.com/someFile.ext&range=1024-2048
....

我也可以将其更改为

http://www.example.com/chunks.php?url=http://url.com/someFile.ext&range=0-1024
http://www.example.com/chunks.php?url=http://url.com/someFile.ext&range=1025-2049
....

取决于我的脚本开始读取文件的位置。

我的第一个方法是使用 cUrl 并设置范围

<?php
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$_GET['url']);
curl_setopt($ch,CURLOPT_RANGE,$_GET['range']);
curl_setopt($ch,CURLOPT_BINARYTRANSFER,1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
$result=curl_exec($ch);
curl_close($ch);
echo $result;
?>

效果很好,但如果范围块大于 1mb,客户端就没有动画onprogress使用ajax的事件。

我可能会使用自定义的CURLOPT_READFUNCTION...但我不知道这是如何工作的...所以我改变了方法并使用了简单的fopen

<?php
$r=explode('-',$_GET['range']);//get (from to) ranges
$cc=($r[1]-$r[0]); //Calculate Client Chunk length
$sc=128; //Set the Server chunk length

$b=""; //Buffer
$bytes=0; //bytes read

$h=fopen($_GET['url'],"rb"); // open the url
fseek($h,$r[0]); // jump to the from pointer retrieved from links

while($bytes<$cc){ //while bytes read is smaller than my client chunk
 $sc=(($bytes+$sc)>$cc?($cc-$bytes):$sc); //prolley an error here 
 //if the server chunk + bytes read is bigger than the client chunk
 //then the server chunk is clinet chunk - bytes read
 $b=fread($h,$sc); // read the buffer
 $bytes+=strlen($b); //add the buffer length to bytes read  
 echo $b;// echo the buffer
 ob_flush(); // flush 
 flush(); // flush
}
fclose($h); //close
?>

现在这有效了...我在客户端上获得了正确的动画,并且最终大小也是正确的,当我使用 fseek && fread 时,指针应该没问题(0-1024,1024-2048)。

但文件已损坏。

现在经过一些测试......这非常慢。

更好的方法是cUrl with CURLOPT_READFUNCTION or fsoket打开...

所以我猜:

<?php
function $READ(){
 //here i need small chuncks of the response flushed. 
}
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$_GET['url']);
curl_setopt($ch,CURLOPT_RANGE,$_GET['range']);
curl_setopt($ch,CURLOPT_BINARYTRANSFER,1);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_READFUNCTION,$READ);
$result=curl_exec($ch);
curl_close($ch);
echo $result;
?>

如果您有更好的解决方案,我愿意接受使用 javascript 和 php 的所有内容。

这样做的目的是创建一个带有简历的下载管理器,将文件存储到window.webkitRequestFileSystem而不填充浏览器的内存。

假设客户端有 8mb 的块,服务器块有 256kb ..

然后该块的每 8mb 都会附加到之前使用以下命令创建的文件中window.webkitRequestFileSystem

每 256kb 我都会更新一次平均下载速度,这样我就可以创建一个漂亮的动画。

服务器上的 php 仅使用 256kb ram,客户端浏览器可以每 8mb 清空一次垃圾收集(理论上)。

EDIT2

对于这段代码我找到了一个解决方案:

该代码允许您获取范围,例如:0-100 并得到这 100 字节分块的输出!

这允许您拥有一个具有连续完美进度条的 AJAX 脚本

<?php
function w($ch,$chunk){ 
 echo $chunk;
 ob_flush();
 flush();
 return strlen($chunk);
};
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$_GET['url']);
curl_setopt($ch,CURLOPT_RANGE,$_GET['range']);
curl_setopt($ch,CURLOPT_BINARYTRANSFER,1);
curl_setopt($ch,CURLOPT_WRITEFUNCTION,w);
curl_exec($ch);
curl_close($ch);
?>

但我希望你们有更好的解决方案!谢谢


我可以让它与 PHP 卷曲一起工作CURLOPT_WRITEFUNCTION回调设置 http://php.net/function.curl_setopt。以下示例回调函数curl_write_flush用于该curl选项写入接收到的每个块并将输出刷新到浏览器。

<?php

/**
 * CURLOPT_WRITEFUNCTION which flushes the output buffer and the SAPI buffer.
 *
 * @param resource $curl_handle
 * @param string   $chunk
 */
function curl_write_flush($curl_handle, $chunk)
{ 
    echo $chunk;

    ob_flush(); // flush output buffer (Output Control configuration specific)
    flush();    // flush output body (SAPI specific)

    return strlen($chunk); // tell Curl there was output (if any).
};

$curl_handle = curl_init($_GET['url']);
curl_setopt($curl_handle, CURLOPT_RANGE, $_GET['range']);
curl_setopt($curl_handle, CURLOPT_BINARYTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_WRITEFUNCTION, 'curl_write_flush');
curl_exec($curl_handle);
curl_close($curl_handle);

我尝试使用小文件和大文件,效果很好,但您无法设置自定义块大小。

下载流的速度与我通过 ISP 获得的速度相同。

如果您有更好的东西,我愿意接受任何答案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

读取用 php 分块的范围块 的相关文章

  • 游戏手柄 JavaScript 未能按预期更新

    我正在尝试让浏览器报告我的 XBOX 控制器的状态 然而 在第一次按下按钮后 它似乎变得 卡住 我究竟做错了什么
  • 将异步事件监听器与 Nestjs EventEmitter 模块和无服务器函数结合使用

    我正在尝试在 Nestjs EventEmitter 模块的帮助下实现具有无服务器 lambda 函数的异步工作线程 处理程序在发出事件时被调用 但该函数在 async await 调用之前关闭 我尝试过同时使用emit and emitA
  • PHP 脚本不断执行 mmap/munmap

    我的 PHP 脚本包含一个循环 它只不过是回显和取消引用指针 如 tab othertab i gt 中的内容 直到昨天 这个脚本开始变得非常慢 比以前慢了 50 倍 之前 它一直运行良好 使用 strace 后 我发现 90 的情况下 脚
  • 当我使用 session_start() 时,Xampp 7.0.1 Apache 崩溃

    当我在 PHP 中使用 session start 启动会话时 我的 Apache 服务器停止工作 我正在使用 Windows 版 Xampp 7 0 1 我的配置文件如下所示 即使我把它放在文件的第一行 它也不起作用 有人知道如何解决这个
  • Paypal 将钱从一个帐户转移到另一个帐户

    我知道这个建议如何汇款至任何 PayPal 账户 https stackoverflow com questions 1559808 paypal api send money to any paypal account但到目前为止我所尝试
  • 使(文本到图像)图像具有一定的宽度但无限的长度?

    我有下面的代码 可以用大量文本生成图像 我希望该图像的宽度为 700 像素 我还希望它保留字符串所具有的段落结构 该字符串来自 MySQL 数据库 我怎样才能实现这一点 font 2 width imagefontwidth font st
  • PHP switch case 在 case 中存在多个值

    我有一个变量保存值 每周 每月 季度 和 年度 还有另一个变量保存值从 1 到 10 switch var2 case 1 var3 Weekly break case 2 var3 Weekly break case 3 var3 Mon
  • php date_parse("2010 年 2 月") 给出日期 == 1

    当没有日期时 我将其称为 date parse 中的错误 d date parse Feb 2010 会给 d day 1 请参阅对此的评论date parse 手册页 http php net manual en function dat
  • PHP 共享标头而不使用服务器端脚本?

    到目前为止我总是通过 PHP 解决简单的问题 您有一个包含页眉 菜单 页脚和内容字段的网站 每个页面的页眉 菜单和页脚通常是相同的 在没有 PHP 或任何其他服务器端语言的情况下 如何使页眉 菜单和页脚数据仅存在于一个文件中 例如 您不会有
  • 使用 file_get_content 发布数据

    我已经做了一些关于如何使用的研究file get content与帖子 我也读过this one https stackoverflow com questions 2445276 how to post data in php using
  • 通过身份验证保护 CodeIgniter 2 应用程序的正确方法是什么?

    I have Ion Auth http benedmunds com ion auth 正确安装并在我的服务器上运行 我也有默认的代码点火器2 新闻 教程在同一个 CI 安装中工作 我只是在玩 并对使用身份验证系统 封闭 或保护整个应用程
  • JavaScript 中的实时摩尔斯电码转换器

    在看到谷歌关于莫尔斯电码 gmail 的愚人节笑话后 我想我应该尝试用 javascript 创建一个实时莫尔斯电码转换器 我正在使用正则表达式和替换将莫尔斯电码更改为字符 例如 replace g a replace g r 我遇到的问题
  • 是否可以将请求标头添加到 CORS 预检请求中?

    我有一个从外部服务器 不是服务器 访问 API 的网站 为网站提供服务 通过简单的XmlHttpRequest 见下文 那个API 需要将用于访问服务的 API 密钥添加为请求标头 然而 正如这些CORS https developer m
  • Outlook 加载项,无法读取未定义的属性“BeginRequestEventArgs”

    我使用 Visual Studio 开发了 Outlook 插件 我的插件有一个按钮 用于填充会议邀请正文中的详细信息并添加所需的与会者 这在 99 的情况下都有效 但是 时不时地它会给我下面的 JavaScript 错误 Uncaught
  • 点击 %40 变为 %2540

    当单击包含 符号的链接时 该网址给我 40 这就是我想要的 但是一旦我点击它 一秒钟后它就在我点击后变成了 2540 单击是在电子邮件内 然后定向到网站 其中 40 更改为 2540 我怎样才能让它停止变化 它现在得到这样的参数 email
  • Javascript onload 不起作用[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我正在使用
  • 弹出窗口的动态高度取决于内容,可能吗?

    是否有可能获得一个宽度始终为 400px 的弹出窗口 但根据弹出窗口中的内容动态高度 我已经看到了这个 但不知道如何将其应用到弹出窗口 调整 iframe 的宽度高度以适应其中的内容 https stackoverflow com ques
  • 具有固定顶部菜单的语义 UI 侧边栏

    Semantic UI 对其进行预警侧边栏页面 http semantic ui com modules sidebar html usage 当侧边栏出现时 固定位置内容可能会出现改变其位置的问题 然后它提供了该问题的两种可能的解决方案
  • 禁用 WooCommerce 手动/编辑订单的电子邮件通知

    需要 WooCommerce 专业知识 我需要禁用手动创建的订单的电子邮件通知 我必须使用处理状态 由于处理订单状态的自定义挂钩 我无法创建自定义状态 理想情况下 手动订单页面中可以勾选一个复选框 勾选后 它将禁止在每种状态下向客户发送电子
  • DOM 解析器 Chrome 扩展内存泄漏

    问题 我开发了一个扩展程序 可以拦截 Web 请求 获取 Web 请求来源的 HTML 并对其进行处理 我使用 DOMParser 来解析 HTML 并且意识到 DOMParser 正在导致大量内存泄漏问题 最终导致 chrome 扩展崩溃

随机推荐