将包含字符串变量内容的文件放在 FTP 站点上(无本地文件)

Posted

技术标签:

【中文标题】将包含字符串变量内容的文件放在 FTP 站点上(无本地文件)【英文标题】:Put a file on FTP site with contents from string variable (no local file) 【发布时间】:2015-06-26 14:11:03 【问题描述】:

我想将文件上传到 FTP 服务器,但文件内容保存在变量中,而不是实际的本地文件中。我想避免使用文件;这是为了避免在(可能)不太安全的系统上处理敏感数据时的安全风险(*),以及最大限度地减少(已经很低的)文件处理开销。 p>

php 的 FTP API 仅提供通过函数 ftp_put 或(当文件已作为文件句柄打开时)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) 保护。


(*) 考虑攻击者对整个文件系统拥有只读控制权的场景。

【问题讨论】:

【参考方案1】:

这可能不是最终的解决方案,但我想还是比原来的方法更好:

您可以使用 PHP 内存流 避免文件系统上出现临时文件。它基本上是一个文件句柄包装器,它(在幕后)不使用实际文件,而是使用一些内存。

所以实际上你仍然使用文件句柄(所以ftp_fput 很高兴),但没有实际的文件(所以没有文件写入磁盘和开销保持最小)。

$tmpfile = fopen('php://memory', 'r+');
fputs($tmpfile, $content);
rewind($tmpfile); // or fseek

请注意,在上传多个文件时,您可以通过对所有文件重复使用相同的文件句柄来进一步减少开销(当然,除非您将过程并行化)。在这种情况下,还要在ftp_fput 之后倒回文件,并使用ftruncate($tmpfile, 0) 截断它。

【讨论】:

为什么这不是最终的解决方案,是因为它有点hacky,还是因为这会带来风险? @Martijn 好吧,对我来说这听起来很老套——没有安全问题。我正在寻找类似ftp_puts(从字符串参数中输入数据)之类的东西,它似乎不存在。一般来说,PHP 的协议“包装器”api 允许规避这种缺失的 API 功能,这对我来说听起来很奇怪,但似乎是处理“虚构”文件的“正常”方式,而其他一些 API 只提供处理文件例如 FTP API。有人可能会觉得它很优雅,也有人会觉得它很老套。 ;) 你会如何发送这个文件名? @user2924019 在之后调用的 ftp 命令中,您总是明确地给出远程文件名。此解决方案以及指定要上传的文件名时都是如此。【参考方案2】:

不涉及本地文件(ftp_fput):

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

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

fclose($stream);

【讨论】:

不工作 -> 警告:ftp_put() 期望参数 3 是有效路径【参考方案3】:

fopen 应该可以通过 ftp 连接:

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

然后使用 fwrite 将字符串写入连接:

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

fwrite 的第二个参数是需要写入的字符串 - 你不需要那里的文件。

【讨论】:

【参考方案4】:

-----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 站点上(无本地文件)的主要内容,如果未能解决你的问题,请参考以下文章

FTP简单记载

批处理文件将文件从一个FTP文件夹移动到同一FTP中的另一个文件夹?

如何设置http代理上ftp并且可以上传?

C#如何将大文件上传到ftp站点

PHP 字符串

win2012服务器怎么启动多个ftp。我建立了多个ftp站点为何不能同时启动?