【问题标题】:How to download LARGE files using AWS getObject and Range?如何使用 AWS getObject 和 Range 下载大文件?
【发布时间】:2015-12-03 17:12:02
【问题描述】:

我正在尝试使用 getObject 方法从 AWS S3 下载大文件。但是对于大文件,页面会关闭。如何使用范围完全下载文件?

function DownloadContent($keyName) {
    $store = array();
    require(__DIR__ . '/../config/s3Config.php');

    if (!$this->s3Client) {
        $this->s3Client = S3Client::factory(array(
                    'key' => $store['s3']['key'],
                    'secret' => $store['s3']['secret']
        ));
    }

    foreach ($keyName as $key => $row) {
        $varFileName = explode('/', $row);
        $bucket = 'my-bucket-name';
        $result = $this->s3Client->getObject(array(
            'Bucket' => $bucket,
            'Key' => $row
        ));

        header("Content-Type: {$result['ContentType']}");
        header("Content-Disposition: attachment; filename=\"{$varFileName[2]}\"");
        header('Expires: 0');header("X-Sendfile: $varFileName[2]");
        echo $result['Body'];
    }
}

【问题讨论】:

  • 您遇到了什么实际错误?您是否在 PHP 中耗尽了内存?这些文件必须加载到 PHP 中,占用内存,因此您需要足够的内存来处理它们。
  • 页面出现错误 ERR_INVALID_RESPONSE,我认为大文件响应正在处理。我想使用 range 属性进行并发下载。
  • 您的 PHP 错误日志中有任何内容吗?
  • 当你谈到“大”时,你不能像这样完全模糊。上次我遇到“大文件问题”时,所有答案都引用了 10 到 100 MB 的大小,而我查看的是 300 到 600 GB。 “大”是非常相对的。
  • 我的文件大小也以 GB 为单位,需要下载。

标签: php amazon-web-services amazon-s3


【解决方案1】:

我知道这是一个相当古老的问题,但似乎没有答案。

$bucket_name = 'my-bucket';
$object_key = 'object-key';

// initialize the S3 client

$client = new S3Client(...);

// register the stream

$client->registerStreamWrapper();

// get the file size

$file_size = filesize('s3://'.$bucket_name.'/'.$object_key);

// get the meta data

$meta_data = $client->headObject([
    'Bucket' => $bucket_name,
    'Key' => $object_key
]);

// get the offset & length

$offset = 0;
$length = $file_size;
$partial_content = false;

if(isset($_SERVER['HTTP_RANGE'])) {
    // the first 500 bytes: bytes=0-499
    // the second 500 bytes: bytes=500-999
    // all bytes except for the first 500 until the end of document: bytes=500-
    // the last 500 bytes of the document: bytes=-500

    preg_match('{bytes=(\d+)?-(\d+)?(,)?}i', $_SERVER['HTTP_RANGE'], $matches);

    if(empty($matches[3])) {
        $partial_content = true;
        $offset = (!empty($matches[1])) ? intval($matches[1]) : 0;
        $length = (!empty($matches[2])) ? intval($matches[2]) : $file_size;
        $length -= $offset;
    }
}

// set the headers for partial content

if($partial_content === true) {
    header('HTTP/1.1 206 Partial Content');
    header('Content-Range: bytes ' . $offset . '-' . ($offset + $length - 1) . '/' . $file_size);
}

// set the regular HTTP headers

header('Content-Type: '.$meta_data['ContentType']);
header('Content-Length: '.$file_size);
header('Content-Disposition: attachment; filename="'.basename($object_key).'"');
header('Accept-Ranges: bytes');

// open a S3 stream to the file

$s3file = fopen('s3://'.$bucket_name.'/'.$object_key, 'rb');

if(!$s3file) {
    throw new Exception('Error opening S§ stream for reading!');
}

// open an output stream

$out = fopen('php://output', 'wb');

// copy data from the S3 stream to the output stream

fseek($s3file, $offset);
stream_copy_to_stream($s3file, $out, $length);

// close the streams

fclose($out);
fclose($s3file);

仅供参考:我已排除多范围选项...

【讨论】:

    猜你喜欢
    • 2021-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-24
    • 1970-01-01
    • 2018-04-06
    • 1970-01-01
    相关资源
    最近更新 更多