在php进程之间的流中传递多个文件

Posted

技术标签:

【中文标题】在php进程之间的流中传递多个文件【英文标题】:Passing multiple files in a stream between php processes 【发布时间】:2017-04-06 21:29:35 【问题描述】:

我需要能够让服务器 A 上的一个 php 用户进程通过 http:// 流从另一台服务器 B 请求数据,并且服务器 B 必须能够通过流返回多个文件。

然后,用户进程必须将其中一个文件发送到外部客户端,并将其他文件本地保存在服务器 A 上(稍后由客户端请求)。基本上,我发送一个带有图像文件的 svg 文件。

我想通过单流来做到这一点。我不想将任何东西保存到服务器 B 上的光盘上,并让用户一一请求。

这样做最干净的方法是什么? 谢谢!

【问题讨论】:

在您问题的当前措辞中,您说“将其他人保存在本地”,但同时也说“我不想将任何内容保存到光盘”。我不明白你想要“在本地保存其他人”是什么意思。 感谢您的评论。我澄清了这个问题。我可能会探索将所有文件发送给客户端的选项,但现在没有必要。 【参考方案1】:

您可以根据需要向流中写入尽可能多的内容:挑战在于接收方(服务器 A 上的 PHP)必须能够识别每个下一个文件的开始位置。您可以自己为此考虑一些协议,例如将TLV 写入流或只是在每个文件的内容前面加上后面的文件内容字节数。请注意,使用此建议您将丢失文件名,因此您也需要合并这些文件名。但最好的方法可能是使用现有标准。在 linux 世界中,人们经常为此使用 TAR 或 TAR-GZ。您可以查看它或使用 ZIP 代替。 This question 包含一些关于如何做到这一点的选项。两个建议都使用库。

另一种选择是使用tempname 的临时文件:虽然它是文件,但您不必管理清理。如果服务器 B 配置为在内存中有 tempdir,则您满足您的要求:-)

Here is a similar question 关于使用 TAR-GZ。 this question 的第二个答案显示了如何通过命令行 tar 命令写入通过 PHP shell 执行从 PHP 调用的标准输出(具有不同级别的启用错误处理的各种选项)。

由于我是在手机上写的,所以我无法尝试提供示例。也许这个周末晚些时候我有时间编辑和添加工作代码来演示。如果你打败了我,请随意自己做:-)

【讨论】:

我将首先探索 ZipArchive 选项。编写协议只是系统可能崩溃的另一个地方。我什至可以考虑直接将存档传递给客户端并由 JS 处理。关于临时文件,我要避免的是服务器 A 独立请求每个文件。 “文件”根本就不是服务器 B 上的真正文件。它们只是刺痛或数据流。【参考方案2】:

这是我根据 van Leeuwen 的一些建议所做的:

在服务器 B 端,我使用了 maennchen/ZipStream-PHP 组件,在代码的不同部分使用了诸如此类的调用:

$zipArchive = new ZipStream();
$zipArchive->addFile($file_name, $image->getImageBlob());
$zipArchive->addFile($this->getId().".svg", $svg);
$zipArchive->finish();

在服务器 B 端,我使用 ZipArchive() 类来处理接收到的文件。

由于两个不同但相互关联的原因,我对解决方案并不完全满意,我希望社区能帮助我改进:

    ZipStream 组件将内容发送到输出缓冲区 直接,在每次 addFile 调用时,作为副作用。这违反了面向对象的好处 实践。最好使用任意流资源 可以由对象返回。 出于某种原因,ZipArchive 仅从文件系统加载文件。我必须将 zip 数据写入文件才能打开 使用 ZipArchive 对象,它可以工作,但是,比方说,在道德上 错了?!

这两个库都没有充分利用 PHP 强大的流功能。关于如何更好地做到这一点的任何想法?

【讨论】:

以上是关于在php进程之间的流中传递多个文件的主要内容,如果未能解决你的问题,请参考以下文章

在进程之间传递值

如何使用共享内存而不是通过多个进程之间的酸洗来传递对象

在不同进程之间传递文件描述符的可移植方式

[网络编程] select/epoll分析

(1) 如何向线程对应的函数传递参数?一个参数如何传递,多个参数如何传递? (2) 深入理解线程与进程的

Linux进程间通信的方式都有哪些