所以我有这段代码,我试图上传大文件按照https://github.com/rackspace/php-opencloud/blob/master/docs/userguide/ObjectStore/Storage/Object.md到Rackspace:
$src_path = 'pathtofile.zip'; //about 700MB
$md5_checksum = md5_file($src_path); //result is f210775ccff9b0e4f686ea49ac4932c2
$trans_opts = array(
'name' => $md5_checksum,
'concurrency' => 6,
'partSize' => 25000000
);
$trans_opts['path'] = $src_path;
$transfer = $container->setupObjectTransfer($trans_opts);
$response = $transfer->upload();
据称上传的文件很好
但是,当我尝试下载此处推荐的文件https://github.com/rackspace/php-opencloud/blob/master/docs/userguide/ObjectStore/USERGUIDE.md:
$name = 'f210775ccff9b0e4f686ea49ac4932c2';
$object = $container->getObject($name);
$objectContent = $object->getContent();
$pathtofile = 'destinationpathforfile.zip';
$objectContent->rewind();
$stream = $objectContent->getStream();
file_put_contents($pathtofile, $stream);
$md5 = md5_file($pathtofile);
md5_file的结果最终与'f210775ccff9b0e4f686ea49ac4932c2'....不同此外,下载的zip最终无法打开/损坏
我做错了什么?
建议只对大于5GB的文件使用多部分上传。对于低于此阈值的文件,可以使用正常的uploadObject方法。
当您使用传输构建器时,它将您的大文件分割成较小的段(您提供部件大小),并同时上传每个段。当这个过程完成后,将创建一个清单文件,其中包含所有这些段的列表。当您下载清单文件时,它会将它们整理在一起,有效地假装是大文件本身。但它实际上只是一个组织者。
回到回答你的问题,清单文件的ETag头并不是你想象的那样计算的。您目前正在做的是获取整个700MB文件的MD5校验和,并将其与清单文件的MD5校验和进行比较。但这些都没有可比性。引用文档:
ETag报头是通过取每个段的ETag值,将它们连接在一起,然后返回结果的MD5校验和来计算的。
使用此DLO操作也有一些缺点,您需要注意:
端到端完整性不能得到保证。最终一致性模型意味着尽管您上传了一个段对象,但它可能不会立即出现在容器列表中。如果在对象出现在容器中之前下载了清单,则该对象将不会成为响应GET请求返回的内容的一部分。
如果你认为在传输中出现了错误,可能是因为HTTP请求在传输过程中失败了。您可以使用重试策略(使用backoff插件)来重试失败的请求。
您还可以打开HTTP日志来检查每个网络事务,以帮助调试。但是要小心,使用上面的命令将HTTP请求体(>25MB)回显到STDOUT中。你可能想用这个代替:
use GuzzlePluginLogLogPlugin;
use GuzzleLogClosureLogAdapter;
$stream = fopen('php://output', 'w');
$logSubscriber = new LogPlugin(new ClosureLogAdapter(function($m) use ($stream) {
fwrite($stream, $m . PHP_EOL);
}), "# Request:n{url} {method}nn# Response:n{code} {phrase}nn# Connect time: {connect_time}nn# Total time: {total_time}", false);
$client->addSubscriber($logSubscriber);
可以看到,您正在使用模板来指定输出的内容。这里有一个完整的模板变量列表