所以我有这个代码,我试图按照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最终无法打开/损坏
我做错了什么?
答案 0 :(得分:0)
建议您仅将multipart uploads用于超过5GB 的文件。对于低于此阈值的文件,您可以使用常规uploadObject方法。
使用转移构建器时,它会将您的大文件分割成较小的片段(您提供部件大小)并同时上传每个片段。完成此过程后,将创建一个清单文件,其中包含所有这些段的列表。下载清单文件时,它会将它们全部整理在一起,实际上假装自己就是大文件。但它真的是一个组织者。
要回到回答您的问题,清单文件的ETag标头不会计算您的想法。您当前正在做的是获取整个700MB文件的MD5校验和,并将其与清单文件的MD5校验和进行比较。但这些都不具有可比性。引用documentation:
ETag标头是通过获取每个段的ETag值,将它们连接在一起,然后返回结果的MD5校验和来计算的。
使用此DLO操作也有一些缺点需要注意:
无法保证端到端的完整性。最终的一致性模型意味着虽然您已上传了一个细分对象,但可能不会立即显示在容器列表中。如果在对象出现在容器中之前下载清单,则该对象将不是响应GET请求而返回的内容的一部分。
如果您认为传输中存在错误,可能是因为HTTP请求在此过程中失败了。您可以使用retry strategies(使用退避插件)重试失败的请求。
您还可以打开HTTP logging来检查每个网络事务以帮助调试。但是要小心,使用上面的方法将HTTP请求体(> 25MB)回显到STDOUT。您可能想要使用它:
use Guzzle\Plugin\Log\LogPlugin;
use Guzzle\Log\ClosureLogAdapter;
$stream = fopen('php://output', 'w');
$logSubscriber = new LogPlugin(new ClosureLogAdapter(function($m) use ($stream) {
fwrite($stream, $m . PHP_EOL);
}), "# Request:\n{url} {method}\n\n# Response:\n{code} {phrase}\n\n# Connect time: {connect_time}\n\n# Total time: {total_time}", false);
$client->addSubscriber($logSubscriber);
如您所见,您正在使用模板来指示输出的内容。有一个完整的模板变量列表here。