S3BucketStreamZip   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 119
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 31.43%
Metric Value
wmc 7
lcom 1
cbo 3
dl 0
loc 119
ccs 11
cts 35
cp 0.3143
rs 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 19 4
A send() 0 52 3
1
<?php
2
/**
3
 * @author Jaisen Mathai <[email protected]>
4
 * @copyright Copyright 2015, Jaisen Mathai
5
 *
6
 * This library streams the contents from an Amazon S3 bucket
7
 *  without needing to store the files on disk or download
8
 *  all of the files before starting to send the archive.
9
 *
10
 * Example usage can be found in the examples folder.
11
 */
12
13
namespace JMathai\S3BucketStreamZip;
14
15
use JMathai\S3BucketStreamZip\Exception\InvalidParameterException;
16
17
use Aws\S3\S3Client;
18
use Aws\S3\Exception\S3Exception;
19
20
use ZipStream;
21
22
class S3BucketStreamZip
23
{
24
  /**
25
   * @var array
26
   *
27
   * {
28
   *   key: your_aws_key,
29
   *   secret: your_aws_secret
30
   * }
31
   */
32
  private $auth   = array();
33
34
  /**
35
   * @var array
36
   *
37
   * See the documentation for the List Objects API for valid parameters.
38
   * Only `Bucket` is required.
39
   *
40
   * http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html
41
   *
42
   * {
43
   *   Bucket: name_of_bucket
44
   * }
45
   */
46
  private $params = array();
47
48
  /**
49
   * @var object
50
   */
51
  private $s3Client;
52
53
  /**
54
   * Create a new ZipStream object.
55
   *
56
   * @param Array $auth     - AWS key and secret
57
   * @param Array $params   - AWS List Object parameters
58
   */
59 4
  public function __construct($auth, $params)
60
  {
61
    // We require the AWS key to be passed in $auth.
62 4
    if(!isset($auth['key']))
63 4
      throw new InvalidParameterException('$auth parameter to constructor requires a `key` attribute');
64
65
    // We require the AWS secret to be passed in $auth.
66 3
    if(!isset($auth['secret']))
67 3
      throw new InvalidParameterException('$auth parameter to constructor requires a `secret` attribute');
68
69
    // We require the AWS S3 bucket to be passed in $params.
70 2
    if(!isset($params['Bucket']))
71 2
      throw new InvalidParameterException('$params parameter to constructor requires a `Bucket` attribute (with a capital B)');
72
73 1
    $this->auth   = $auth;
74 1
    $this->params = $params;
75
76 1
    $this->s3Client = S3Client::factory($this->auth);
77 1
  }
78
79
  /**
80
   * Stream a zip file to the client
81
   *
82
   * @param String $filename  - Name for the file to be sent to the client
83
   * @param Array  $params    - Optional parameters
84
   *  {
85
   *    expiration: '+10 minutes'
86
   *  }
87
   */
88
  public function send($filename, $params = array())
89
  {
90
    // Set default values for the optional $params argument
91
    if(!isset($params['expiration']))
92
      $params['expiration'] = '+10 minutes';
93
94
    // Initialize the ZipStream object and pass in the file name which
95
    //  will be what is sent in the content-disposition header.
96
    // This is the name of the file which will be sent to the client.
97
    $zip = new ZipStream\ZipStream($filename);
98
99
    // Get a list of objects from the S3 bucket. The iterator is a high
100
    //  level abstration that will fetch ALL of the objects without having
101
    //  to manually loop over responses.
102
    $result = $this->s3Client->getIterator('ListObjects', $this->params);
103
104
    // We loop over each object from the ListObjects call.
105
    foreach($result as $file)
106
    {
107
      // We need to use a command to get a request for the S3 object
108
      //  and then we can get the presigned URL.
109
      $command = $this->s3Client->getCommand('GetObject', array(
110
        'Bucket' => $this->params['Bucket'],
111
        'Key' => $file['Key']
112
      ));
113
      $signedUrl = $command->createPresignedUrl($params['expiration']);
114
      
115
      // Get the file name on S3 so we can save it to the zip file 
116
      //  using the same name.
117
      $fileName = basename($file['Key']);
118
119
      // We want to fetch the file to a file pointer so we create it here
120
      //  and create a curl request and store the response into the file 
121
      //  pointer.
122
      // After we've fetched the file we add the file to the zip file using
123
      //  the file pointer and then we close the curl request and the file 
124
      //  pointer.
125
      // Closing the file pointer removes the file.
126
      $fp = tmpfile();
127
      $ch = curl_init($signedUrl);
128
      curl_setopt($ch, CURLOPT_TIMEOUT, 120);
129
      curl_setopt($ch, CURLOPT_FILE, $fp);
130
      curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
131
      curl_exec($ch);
132
      curl_close($ch);
133
      $zip->addFileFromStream($fileName, $fp);
134
      fclose($fp);
135
    }
136
137
    // Finalize the zip file.
138
    $zip->finish();
139
  }
140
}
141