【发布时间】:2012-03-17 10:12:05
【问题描述】:
我正在尝试将相当大的数据块写入通过 php.ini 中的 fopen() 打开的文件。我使用的协议包装器是 ftp,因此该文件对于运行 php 代码的服务器是远程的。我正在写入的文件位于 Windows 服务器上。
我确认该文件实际上是由我的 php 代码创建的,但问题是文件中的数据不存在 (0KB) 或写入文件过早停止。不知道为什么会这样。
这是我用于处理操作的代码:
$file_handle = fopen($node['ftp'].$path_to_lut, "wb", 0, $node['ftp_context']);
include_once($file);
if ($file_handle)
{
fwrite($file_handle, $string); //$string is inside included $file
fclose($file_handle);
} else {
die('There was a problem opening the file.');
}
当我在本地计算机上托管此代码时,它运行良好,但当我将它上传到我的网络主机(Rackspace Cloud)时,它失败了。这让我相信这是与我在 Rackspace 的服务器配置有关的问题,但想知道我是否可以对我的 php 代码做任何事情以使其更健壮。
有什么办法可以确保 fwrite 真正完成将字符串写入远程机器?
谢谢!
好的,我更改了写入文件的代码,如下所示:
if ($file_handle)
{
if ($bytesWritten = fwrite($file_handle, $string) ) {
echo "There were " . $bytesWritten . " bytes written to the text file.";
}
if (!fflush($file_handle)) {
die("There was a problem outputting all the data to the text file.");
}
if (!fclose($file_handle)) {
die("There was a problem closing the text file.");
}
} else {
die("No file to write data to. Sorry.");
}
奇怪的是echo语句显示如下:
有 10330 字节写入文本文件。
然而,当我通过 FTP 验证文本文件大小时,它显示为 0K,而文件中的数据实际上已被截断。我无法想象它与 FTP 服务器本身有关,因为如果 PHP 托管在 Rackspace Cloud 上的机器以外的机器上,它就可以工作。
** 更新 ** 我与 Rackspace Cloud 代表交谈过,他提到如果您要从他们的服务器上进行 ftp,他们需要被动 ftp。我设置了远程服务器来处理被动 ftp 连接,并验证了被动 ftp 现在可以通过 OSX Transmit ftp 客户端在远程服务器上运行。我补充说:
ftp_pasv($file_handle, true);
就在 fopen() 语句之后,但我从 PHP 收到一个错误,说我没有为 ftp_pasv() 提供有效资源。如何确保与 PHP 建立的 ftp 站点的连接是 PASV 而不是 ACTIVE 并且仍然使用 fwrite()?顺便说一句,我注意到 Windows 机器报告我的 PHP 代码正在写入的文件在磁盘上是 4096 字节。它永远不会超过这个数量。这导致我将 output_buffering php 值更改为 65536 只是为了进行故障排除,但这也没有解决问题。 . .
** 更新部分 DUEX **
在 Rackspace 云站点产品上解决我的虚拟服务器上的问题被证明太困难了,因为它们没有提供足够的管理员权限。我在 Rackspace 的 Cloud Server 产品上创建了一个非常小的云服务器,并将所有内容配置到我仍然看到 fwrite() 出现相同错误的地步。为了确保我可以将文件从该服务器写入远程服务器,我在云服务器上的 bash shell 中使用了基本的 ftp 命令。它工作得很好。因此,我假设 fwrite() 的 php 实现中存在错误,并且可能是由于某种类型的数据限制问题。当我从本地环境写入远程服务器时,与 Rackspace 云服务器上提供的相比,它的速度较慢,它工作正常。有什么方法可以有效地降低写入速度?随便问问吧:)
** 更新第三部分 *
所以,我接受了@a sad dude 的建议并实现了一个功能,该功能可能会帮助尝试写入新文件并通过 ftp 将其全部发送出去的人:
function writeFileAndFTP($filename=null, $data=null, $node=null, $local_path=null, $remote_path=null)
{
// !Determin the path and the file to upload from the webserver
$file = $local_path.'/'.$filename;
// !Open a new file to write to on the local machine
if (!($file_handle = fopen($file, "wb", 0))) {
die("There was a problem opening ".$file." for writing!");
}
// !Write the file to local disk
if ($bytesWritten = fwrite($file_handle, $data) ) {
//echo "There were " . $bytesWritten . " bytes written to " . $file;
}
// !Close the file from writing
if (!fclose($file_handle)) {
die("There was a problem closing " . $file);
}
// !Create connection to remote FTP server
$ftp_cxn = ftp_connect($node['addr'], $node['ftp_port']) or die("Couldn't connect to the ftp server.");
// !Login to the remote server
ftp_login($ftp_cxn, $node['user'], getPwd($node['ID'])) or die("Couldn't login to the ftp server.");
// !Set PASV or ACTIVE FTP
ftp_pasv($ftp_cxn, true);
// !Upload the file
if (!ftp_put($ftp_cxn, $remote_path.'/'.$filename, $file, FTP_ASCII)) {
die("There was an issue ftp'ing the file to ".$node['addr'].$remote_path);
}
// !Close the ftp connection
ftp_close($ftp_cxn);
}
【问题讨论】:
-
include_once($file);- 代码在哪里? -
如下所示:
$string = "a string about 20 lines long"; -
var_dump($node['ftp_context']);输出什么? (删除用户名/密码)。 -
resource(32) 类型(流上下文)
-
另外,代码
var_dump(stream_get_meta_data($file_handle));输出:array(10) { ["wrapper_data"]=> NULL ["wrapper_type"]=> string(3) "ftp" ["stream_type"]=> string(14) "tcp_socket/ssl" ["mode"]=> string(2) "r+" ["unread_bytes"]=> int(0) ["seekable"]=> bool(false) ["uri"]=> string(119) "ftp://user:pass@mydomain.com:21/vars.txt" ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) }