我无法从我们的某台服务器上传文件到S3。我们使用S3存储备份,所有服务器都运行Ubuntu 8.04,PHP 5.2.4和libcurl 7.18.0。每当我尝试上传文件时,亚马逊都会返回RequestTimeout错误。我知道我们当前版本的libcurl中存在一个错误,导致上传超过200MB。因此,我们将备份拆分为较小的文件。
我们在亚马逊的EC2上托管服务器,在客户的“私有云”(公司防火墙后面的VMWare ESX盒)上托管服务器。我遇到问题的特定服务器托管在客户的私有云上。
我们使用http://undesigned.org.za/2007/10/22/amazon-s3-php-class中的Amazon S3 PHP类。我尝试过200MB,100MB和50MB文件,结果相同。我们使用以下内容上传文件:
$s3 = new S3($access_key, $secret_key, false);
$success = $s3->putObjectFile($local_path, $bucket_name,
$remote_name, S3::ACL_PRIVATE);
我尝试设置curl_setopt($curl, CURLOPT_NOPROGRESS, false);
以在上传文件时查看进度条。我第一次使用此选项运行它设置它有效。但是,每次都失败了。它似乎以大约3Mb / s上传文件5-10秒然后下降到0.在20秒后坐在0,亚马逊返回“RequestTimeout - 你的套接字连接到服务器没有读取或写入超时期间。空闲连接将被关闭。“错误。
我尝试将S3类更新为GitHub的最新版本,但没有区别。我还找到了Amazon S3 Stream Wrapper类,并尝试使用以下代码:
include 'gs3.php';
define('S3_KEY', 'ACCESSKEYGOESHERE');
define('S3_PRIVATE','SECRETKEYGOESHERE');
$local = fopen('/path/to/backup_id.tar.gz.0000', 'r');
$remote = fopen('s3://bucket-name/customer/backup_id.tar.gz.0000', 'w+r');
$count = 0;
while (!feof($local))
{
$result = fwrite($remote, fread($local, (1024 * 1024)));
if ($result === false)
{
fwrite(STDOUT, $count++.': Unable to write!'."\n");
}
else
{
fwrite(STDOUT, $count++.': Wrote '.$result.' bytes'."\n");
}
}
fclose($local);
fclose($remote);
此代码一次读取一个MB文件,以便将其流式传输到S3。对于一个50MB的文件,我得到“1:写入1048576字节”49次(第一个数字当然每次都改变)但是在循环的最后一次迭代中我得到一个错误,上面写着“通知:fputs():发送8192字节失败,errno = 11资源在第230行的/path/to/http.php中暂时不可用“。
我首先想到的是这是一个网络问题。我们打电话给客户并解释了问题,并要求他们查看他们的防火墙,看看他们是否放弃了任何东西。据他们的网络管理员说,流量很好。
我不知道接下来我能做些什么。我一直在手动运行备份,并使用SCP将它们转移到另一台机器并上传它们。这显然不太理想,我们将非常感谢任何帮助。
更新 - 2011年6月23日
我尝试了下面的许多选项,但它们都提供了相同的结果。我发现即使尝试将有问题的服务器中的文件scp到另一台服务器也会立即停止并最终超时。但是,我可以使用scp从另一台机器下载相同的文件。这让我更加确信这是客户端的网络问题,我们将非常感谢任何进一步的建议。
答案 0 :(得分:4)
存在此问题是因为您尝试再次上载同一文件。例如:
$s3 = new S3('XXX','YYYY', false);
$s3->putObjectFile('file.jpg','bucket-name','file.jpg');
$s3->putObjectFile('file.jpg','bucket-name','newname-file.jpg');
要修复它,只需复制文件并为其指定新名称,然后正常上传。
示例:
$s3 = new S3('XXX','YYYY', false);
$s3->putObjectFile('file.jpg','bucket-name','file.jpg');
now rename file.jpg to newname-file.jpg
$s3->putObjectFile('newname-file.jpg','bucket-name','newname-file.jpg');
答案 1 :(得分:2)
我以另一种方式解决了这个问题。我的错误是,filesize()函数返回无效的缓存大小值。所以只需使用clearstatcache()
答案 2 :(得分:1)
我多次经历过同样的问题。
我现在有很多脚本,它们不断地将文件上传到S3。
我可以提供的最佳解决方案是使用Zend库(流包装器或直接S3 API)。
http://framework.zend.com/manual/en/zend.service.amazon.s3.html
自Zend框架的最新版本发布以来,我没有看到任何超时问题。但是,如果您发现自己仍然遇到问题,可以通过简单的调整来解决问题。
只需打开文件Zend / Http / Client.php并修改$ config数组中的'timeout'值即可。在撰写本文时,它存在于第114行。在最新版本之前,我的运行速度为120秒,但现在情况正常,10秒超时。
希望这有帮助!
答案 3 :(得分:1)
有很多可用的解决方案。我有这个确切的问题,但我不想编写代码并找出问题所在。
最初我正在寻找在Linux机器上安装S3存储桶的可能性,发现了一些有趣的东西:
s3fs - http://code.google.com/p/s3fs/wiki/InstallationNotes - 这确实对我有用。它使用FUSE文件系统+ rsync来同步S3中的文件。它键入了本地系统中所有文件名的副本。使它看起来像一个文件/文件夹。
这节省了我们时间的BUNCH +编写用于传输文件的代码的麻烦。
现在,当我试图查看是否还有其他选项时,我发现了一个可在CLI中运行的ruby脚本,可以帮助您管理S3帐户。
s3cmd - http://s3tools.org/s3cmd - 这看起来很清楚。
[UPDATE] 找到了另一个CLI工具 - s3sync
s3sync - https://forums.aws.amazon.com/thread.jspa?threadID=11975&start=0&tstart=0 - 在亚马逊AWS社区中找到。
我没有看到它们两者不同,如果你不担心磁盘空间,那么我会选择s3fs而不是s3cmd。磁盘让您感觉更舒服+您可以看到磁盘中的文件。
希望它有所帮助。
答案 4 :(得分:1)
您应该查看AWS PHP SDK。这是以前称为tarzan和cloudfusion的AWS PHP库。
http://aws.amazon.com/sdkforphp/
此类附带的S3类坚如磐石。我们一直用它来上传多GB文件。