0

I need to be able for one php user process on a server A to request data via http:// stream from another server B and the server B must be able to return several files via the stream.

The user process, then, must send one of the files to the external client and save the others locally on server A (to be requested by the client later). Basically, I am sending a svg file with accompanying image files.

I would like to do this via the single stream. I don't want to save anything to disc on server B and have the user requested it one by one.

What is the cleanest way of doing this? Thanks!

DarkBee
  • 16,592
  • 6
  • 46
  • 58
Vakarelov
  • 97
  • 6
  • 1
    In the current wording of your question you say "save the others locally", but at the same time also "I don't want to save anything to disc". I do not understand what you want or mean with "save the others locally" then. – pjvleeuwen Apr 06 '17 at 21:43
  • Thanks for the comment. I clarified the question. I may explore the option of send all the file to the client, later but for now this is not necessary. – Vakarelov Apr 06 '17 at 23:04

2 Answers2

0

You can write as much to the stream as you want: the challenge is that the receiving side (the PHP on server A) must be able to recognize where each next file begins. You can think of some protocol for this yourself, e.g. write TLV to the stream or just prefix the contents of each file with the amount of bytes file-content that follow. Note that with this suggestion you will lose the filenames, so you would need to incorporate those too. But the best way is probably to use an existing standard. In the linux world people often use TAR or TAR-GZ for that.You can look into that or use ZIP instead. This question contains some options on how to do that. Both suggestions use a library.

Another alternative is using a temp file using tempname: although it is to file you do not have to manage the cleanup. If server B is configured to have the tempdir in memory you meet your requirement :-)

Here is a similar question on using TAR-GZ. And the second answer to this question shows how to do that via the command line tar command writing to stdout called from PHP via PHP shell execution (various options for that with varying levels of enabling error handling).

Since I write this on the phone I cannot try and provide an example. Maybe later this weekend I have time to edit and add working code to demonstrate. Feel free to do that yourself if you beat me to it :-)

Community
  • 1
  • 1
pjvleeuwen
  • 4,215
  • 1
  • 18
  • 31
  • I will explore ZipArchive option first. Writing a protocol is just another place where the system may break. I may even consider passing the archive to the client direly and have it handled by JS. About the temp file, what I want to avoid is server A requesting each file independently. The "files" are never really files on server B at all. They are just stings or data-streams. – Vakarelov Apr 07 '17 at 19:35
0

Here is what I did following some of the recommendations of van Leeuwen:

On server B side, I used the maennchen/ZipStream-PHP component, using calls such as these, in different part of the code:

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

On server B side I used the ZipArchive() class to process the received file.

I am not completely happy with the solution for two different but connected reasons, and I am hoping that the community will help me improve:

  1. The ZipStream component sends the content to the output buffer directly, at every addFile call, as a side-effect. This violates object-oriented good practice. It would be better to use an arbitrary stream resource that can be returned by the object.
  2. ZipArchive, for some reason, only loads files from the file system. I had to write the zip data to a file to be able to open in with the ZipArchive object, which works, but is, let's say, morally wrong?!

Both libraries do not exploit sufficiently well PHP's awesome power of streams. Any thoughts about how to do this better?

Vakarelov
  • 97
  • 6