将文件放在 FTP 站点上,内容来自字符串变量(无本地文件)
Put a file on FTP site with contents from string variable (no local file)
我想将文件上传到 FTP 服务器,但文件内容保存在一个变量中,而不是实际的本地文件中。我想避免使用文件;这是为了避免在(可能)不太安全的系统上处理敏感数据时出现安全风险(*),并尽量减少文件处理的(已经很低的)开销.
但是PHP的FTP API只提供通过函数ftp_put
or (when the file is already opened as a file handle) ftp_fput
.
从本地文件上传文件
目前,我将此功能与一个临时文件一起使用,我在其中写入了上传前的内容:
$tmpfile = tmpfile();
fwrite($tmpfile, $content);
fseek($tmpfile, 0);
ftp_fput($ftp, $filename, $tmpfile, FTP_BINARY);
有没有更简单的方法,根本不使用本地 (PHP) 站点上的文件?
有ftp_raw
可用于发送任意命令,所以我可以手动发出PUT
命令,但是我没有看到手动将数据写入数据的方法频道...
我不知道它是否重要,但是 FTP 连接是通过 SSL (ftp_ssl_connect
) 保护的。
(*) 考虑攻击者对整个文件系统具有只读控制权的场景。
fopen 应该可以通过 ftp 连接:
http://php.net/manual/en/function.fopen.php
然后使用 fwrite 将字符串写入连接:
http://php.net/manual/en/function.fwrite.php
fwrite 的第二个参数是需要写入的字符串 - 你不需要那里的文件。
这可能不是最终的解决方案,但我想仍然比原来的方法更好:
您可以通过使用PHP 内存流 来避免文件系统上的临时文件。它基本上是一个文件句柄包装器,它(在幕后)不使用实际文件而是使用一些内存块。
所以实际上你仍然使用文件句柄(所以ftp_fput
很高兴),但没有实际的文件(所以没有文件写入磁盘并且开销保持在最低限度)。
$tmpfile = fopen('php://memory', 'r+');
fputs($tmpfile, $content);
rewind($tmpfile); // or fseek
请注意,当上传多个文件时,您可以通过对所有文件重复使用相同的文件句柄来进一步减少开销(当然,除非您并行处理该过程)。在这种情况下,还要在 ftp_fput
之后倒回文件并使用 ftruncate($tmpfile, 0)
.
截断它
-----FTP PUT 内容 (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);
不涉及本地文件 (ftp_fput):
$stream = fopen('php://memory','r+');
fwrite($stream, $newFileContent);
rewind($stream);
$success = ftp_fput($connectionId, "remoteFileName", $stream, FTP_BINARY);
fclose($stream);
我想将文件上传到 FTP 服务器,但文件内容保存在一个变量中,而不是实际的本地文件中。我想避免使用文件;这是为了避免在(可能)不太安全的系统上处理敏感数据时出现安全风险(*),并尽量减少文件处理的(已经很低的)开销.
但是PHP的FTP API只提供通过函数ftp_put
or (when the file is already opened as a file handle) ftp_fput
.
目前,我将此功能与一个临时文件一起使用,我在其中写入了上传前的内容:
$tmpfile = tmpfile();
fwrite($tmpfile, $content);
fseek($tmpfile, 0);
ftp_fput($ftp, $filename, $tmpfile, FTP_BINARY);
有没有更简单的方法,根本不使用本地 (PHP) 站点上的文件?
有ftp_raw
可用于发送任意命令,所以我可以手动发出PUT
命令,但是我没有看到手动将数据写入数据的方法频道...
我不知道它是否重要,但是 FTP 连接是通过 SSL (ftp_ssl_connect
) 保护的。
(*) 考虑攻击者对整个文件系统具有只读控制权的场景。
fopen 应该可以通过 ftp 连接:
http://php.net/manual/en/function.fopen.php
然后使用 fwrite 将字符串写入连接:
http://php.net/manual/en/function.fwrite.php
fwrite 的第二个参数是需要写入的字符串 - 你不需要那里的文件。
这可能不是最终的解决方案,但我想仍然比原来的方法更好:
您可以通过使用PHP 内存流 来避免文件系统上的临时文件。它基本上是一个文件句柄包装器,它(在幕后)不使用实际文件而是使用一些内存块。
所以实际上你仍然使用文件句柄(所以ftp_fput
很高兴),但没有实际的文件(所以没有文件写入磁盘并且开销保持在最低限度)。
$tmpfile = fopen('php://memory', 'r+');
fputs($tmpfile, $content);
rewind($tmpfile); // or fseek
请注意,当上传多个文件时,您可以通过对所有文件重复使用相同的文件句柄来进一步减少开销(当然,除非您并行处理该过程)。在这种情况下,还要在 ftp_fput
之后倒回文件并使用 ftruncate($tmpfile, 0)
.
-----FTP PUT 内容 (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);
不涉及本地文件 (ftp_fput):
$stream = fopen('php://memory','r+');
fwrite($stream, $newFileContent);
rewind($stream);
$success = ftp_fput($connectionId, "remoteFileName", $stream, FTP_BINARY);
fclose($stream);