如何使用AWS getObject和Range下载LARGE文件?

时间:2015-12-03 17:12:03

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

我正在尝试使用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'];
    }
}

1 个答案:

答案 0 :(得分:0)

我知道这是一个比较老的问题,尽管似乎没有答案。

$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);

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