Put a file on FTP site with contents from string v

2020-07-05 05:03发布

问题:

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.

回答1:

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).



回答2:

With no local file involved (ftp_fput):

$stream = fopen('php://memory','r+');
fwrite($stream, $newFileContent);
rewind($stream);

$success = ftp_fput($connectionId, "remoteFileName", $stream, FTP_BINARY);

fclose($stream);


回答3:

fopen should be able to connect via ftp:

http://php.net/manual/en/function.fopen.php

and then use fwrite to write string to connection:

http://php.net/manual/en/function.fwrite.php

Second parameter of fwrite is string that need to be written - you don't need file there.



回答4:

-----FTP PUT contents (php 7.0) ---

$tmpFile = tmpfile();

fwrite($tmpFile, $contents);
rewind($tmpFile);

$tmpMetaData = stream_get_meta_data($tmpFile);

if (ftp_put($ftpObj, $remoteFile, $tmpMetaData['uri'], FTP_ASCII)) {
    echo "success";
} else {
    echo "fail";
}

fclose($tmpFile);


标签: php ftp