I want to upload a file to an FTP server, but the file content is held in a variable, not in an actual local file. I want to avoid using a file; this is to avoid security risks when dealing with sensitive data on a (possibly) not-so-secure system(*), as well as to minimize the (already low) overhead of file handling.
But PHP’s FTP API only offers uploading files from local files via the function ftp_put
or (when the file is already opened as a file handle) ftp_fput
.
Currently, I use this function with a temporary file in which I write the contents before the upload:
$tmpfile = tmpfile(); fwrite($tmpfile, $content); fseek($tmpfile, 0); ftp_fput($ftp, $filename, $tmpfile, FTP_BINARY);
Is there a simpler way without using files on the local (PHP) site at all?
There is ftp_raw
which can be used to send arbitrary commands, so I could issue the PUT
command manually, however I don’t see a way to manually write the data on the data channel…
I don’t know if it is important, but the FTP connection is secured with SSL (ftp_ssl_connect
).
(*) Consider the scenario where an attacker has read-only control over the entire file system.
Advertisement
Answer
This may be no ultimate solution but I guess is still better than the original approach:
You can avoid temporary files on the file system by using a PHP memory stream. It basically is a file handle wrapper which (behind the scenes) uses no actual file but instead some chunk of memory.
So virtually you still use a file handle (so ftp_fput
is happy), but no actual file (so no file is written to the disk and the overhead is kept minimal).
$tmpfile = fopen('php://memory', 'r+'); fputs($tmpfile, $content); rewind($tmpfile); // or fseek
Note that when uploading multiple files, you can further minimize overhead by reusing the same file handle for all files (unless you parallelize the procedure, of course). In this case, also rewind the file after ftp_fput
as well as truncate it using ftruncate($tmpfile, 0)
.