Search code examples
phpftpstreamzipphp-ziparchive

Create zip archive and stream it to ftp server


I am trying to create a zip file from local files and stream it directly to an ftp (without writing the zip to disk first). I have no problems with zipping itself but it seems like the ZipArchive class doesn't recognize the ftp stream wrapper.

The following code is the simplest thing I could come up with that will illustrate the problem

<?php

$zip = new ZipArchive();
var_dump($zip->open('ftp://[username]:[password]@[hostname.net]/public_html/test.zip', ZipArchive::OVERWRITE));

$zip->addFile(realpath('/input.txt'), 'input.txt');

var_dump($zip->close());

The $zip->open call returns true while $zip->close returns false. I can't find a way to get an error message or something that can be more specific than just there is an error. The question is what am I doing wrong, or I can't do these kind of stuff with the ZipArchive class.


Solution

  • I've tested your code on my Ubuntu system and I can confirm that it does'nt work.
    By using the "strace" utility, I've seen that the PHP is handling the "$filename" argument as if it was a local file name, as you can see below:

    lstat64("/var/www/test/ftp://myuser:[email protected]/tmp/test.zip", 0xbfcbb008) = -1 ENOENT (No such file or directory)
    lstat64("/var/www/test/ftp://myuser:[email protected]/tmp", 0xbfcbaeb8) = -1 ENOENT (No such file or directory)
    lstat64("/var/www/test/ftp://myuser:[email protected]", 0xbfcbad68) = -1 ENOENT (No such file or directory)
    lstat64("/var/www/test/ftp:", 0xbfcbac28) = -1 ENOENT (No such file or directory)
    

    The "/var/www/test" prefix is the path of my PHP test script.
    So, it seems that effectively the ZipArchive::open() method cannot handle URL filenames.
    Looking at the PHP source code, and I've discovered that the ZipArchive::open() method calls the "zip_open" function.
    The PHP manual page for the "fopen" function states:

    If filename is of the form "scheme://...", it is assumed to be a URL and PHP will search for a protocol handler (also known as a wrapper) for that scheme. If no wrappers for that protocol are registered, PHP will emit a notice to help you track potential problems in your script and then continue as though filename specifies a regular file.

    This post, found in the PHP manual page for the "stream_wrapper_register" function, states that zip_open() ignores custom stream wrappers, but the above test shows that it also ignores standard stream wrappers.
    It's also true that neither ZipArchive::open() manual page nor the zip_open manual page explicitly say that the "$filename" parameter can be a URL.