1

所以我有这段代码,我正在尝试按照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 最终无法打开/损坏

我做错了什么?

4

1 回答 1

0

建议您仅对超过 5GB的文件使用分段上传。对于低于此阈值的文件,您可以使用普通的uploadObject方法。

当您使用传输构建器时,它会将您的大文件分割成更小的片段(您提供部分大小)并同时上传每个片段。此过程完成后,将创建一个清单文件,其中包含所有这些段的列表。当您下载清单文件时,它会将它们全部整理在一起,有效地伪装成大文件本身。但它只是一个真正的组织者。

回到回答您的问题,清单文件的 ETag 标头不是按照您的想法计算的。您目前正在做的是获取整个 700MB 文件的 MD5 校验和,并将其与清单文件的 MD5 校验和进行比较。但这些没有可比性。引用文档

ETag 头是通过获取每个段的 ETag 值,将它们连接在一起,然后返回结果的 MD5 校验和来计算的。

您还需要注意使用此 DLO 操作的缺点:

无法保证端到端的完整性。最终一致性模型意味着虽然您已经上传了一个段对象,但它可能不会立即出现在容器列表中。如果您在对象出现在容器中之前下载清单,则该对象将不是响应 GET 请求而返回的内容的一部分。

如果您认为传输过程中出现错误,可能是因为 HTTP 请求在此过程中失败。您可以使用重试策略(使用退避插件)重试失败的请求。

您还可以打开HTTP 日志记录以检查每个网络事务以帮助调试。不过要小心,使用上面的内容将 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);

如您所见,您正在使用模板来指示输出的内容。这里有模板变量的完整列表。

于 2014-08-04T09:59:46.087 回答