1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace ContentsFile\Aws; |
4
|
|
|
|
5
|
|
|
use Aws\Sdk; |
6
|
|
|
use Cake\Core\Configure; |
7
|
|
|
use Cake\Network\Exception\InternalErrorException; |
8
|
|
|
use Cake\Network\Exception\NotFoundException; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* S3 |
12
|
|
|
* AWS SDKのS3関係の処理 |
13
|
|
|
* @author hagiwara |
14
|
|
|
*/ |
15
|
|
|
class S3 |
16
|
|
|
{ |
17
|
|
|
private $client; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* __construct |
21
|
|
|
* @author hagiwara |
22
|
|
|
*/ |
23
|
|
|
public function __construct() |
24
|
|
|
{ |
25
|
|
|
// S3に必要な設定がそろっているかチェックする |
26
|
|
|
$S3Setting = Configure::read('ContentsFile.Setting.S3'); |
27
|
|
View Code Duplication |
if ( |
|
|
|
|
28
|
|
|
!is_array($S3Setting) || |
29
|
|
|
!array_key_exists('bucket', $S3Setting) || |
30
|
|
|
!array_key_exists('tmpDir', $S3Setting) || |
31
|
|
|
!array_key_exists('fileDir', $S3Setting) |
32
|
|
|
) { |
33
|
|
|
throw new InternalErrorException('contentsFileS3Config paramater shortage'); |
34
|
|
|
} |
35
|
|
|
// S3に接続するためのクライアントを用意します。 |
36
|
|
|
$config = array( |
37
|
|
|
'version' => 'latest', |
38
|
|
|
'region' => 'ap-northeast-1' |
39
|
|
|
); |
40
|
|
|
// key, secretが指定されている場合はcredentialsを設定する |
41
|
|
|
$key = Configure::read('ContentsFile.Setting.S3.key'); |
42
|
|
|
$secret = Configure::read('ContentsFile.Setting.S3.secret'); |
43
|
|
|
if (!empty($key) && !empty($secret)) { |
44
|
|
|
$config['credentials'] = array( |
45
|
|
|
'key'=> $key, |
46
|
|
|
'secret' => $secret, |
47
|
|
|
); |
48
|
|
|
} |
49
|
|
|
$sdk = new Sdk($config); |
50
|
|
|
$this->client = $sdk->createS3(); |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* getClient |
55
|
|
|
* clientを取得 |
56
|
|
|
* @author hagiwara |
57
|
|
|
*/ |
58
|
|
|
public function getClient() |
59
|
|
|
{ |
60
|
|
|
return $this->client; |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* upload |
65
|
|
|
* S3へのファイルアップロード |
66
|
|
|
* @author hagiwara |
67
|
|
|
*/ |
68
|
|
|
public function upload($filepath, $filename) |
69
|
|
|
{ |
70
|
|
|
// アップロードするべきファイルがない場合 |
71
|
|
|
if (!file_exists($filepath)) { |
72
|
|
|
throw new InternalErrorException('upload file not found'); |
73
|
|
|
} |
74
|
|
|
$bucketName = Configure::read('ContentsFile.Setting.S3.bucket'); |
75
|
|
|
$mimetype = mime_content_type($filepath); |
76
|
|
|
|
77
|
|
|
// ファイルのアップロード |
78
|
|
|
$data = file_get_contents($filepath); |
79
|
|
|
|
80
|
|
|
return $this->client->putObject([ |
81
|
|
|
'Bucket' => $bucketName, |
82
|
|
|
'Key' => $filename, |
83
|
|
|
'Body' => $data, |
84
|
|
|
'ContentType' => $mimetype |
85
|
|
|
]); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* upload |
90
|
|
|
* S3からのファイルダウンロード |
91
|
|
|
* @author hagiwara |
92
|
|
|
*/ |
93
|
|
|
public function download($filename) |
94
|
|
|
{ |
95
|
|
|
// ファイルが存在しない場合は404 |
96
|
|
|
if (!$this->fileExists($filename)) { |
97
|
|
|
throw new NotFoundException('404 error'); |
98
|
|
|
} |
99
|
|
|
return $this->client->getObject([ |
100
|
|
|
'Bucket' => Configure::read('ContentsFile.Setting.S3.bucket'), |
101
|
|
|
'Key' => $filename |
102
|
|
|
]); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* copy |
107
|
|
|
* S3上でのファイルコピー |
108
|
|
|
* @author hagiwara |
109
|
|
|
*/ |
110
|
|
|
public function copy($oldFilename, $newFilename) |
111
|
|
|
{ |
112
|
|
|
// ファイルが存在しない |
113
|
|
|
if (!$this->fileExists($oldFilename)) { |
114
|
|
|
return false; |
115
|
|
|
} |
116
|
|
|
// 権限不足のExceptionはそのまま出す |
117
|
|
|
$this->client->copyObject(array( |
118
|
|
|
'Bucket' => Configure::read('ContentsFile.Setting.S3.bucket'), |
119
|
|
|
'Key' => $newFilename, |
120
|
|
|
'CopySource' => Configure::read('ContentsFile.Setting.S3.bucket') . '/' . $oldFilename, |
121
|
|
|
)); |
122
|
|
|
return true; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* delete |
127
|
|
|
* S3上でのファイル削除 |
128
|
|
|
* @author hagiwara |
129
|
|
|
*/ |
130
|
|
|
public function delete($filename) |
131
|
|
|
{ |
132
|
|
|
// 削除するファイルが存在しない |
133
|
|
|
if (!$this->fileExists($filename)) { |
134
|
|
|
return false; |
135
|
|
|
} |
136
|
|
|
// 権限不足のExceptionはそのまま出す |
137
|
|
|
$this->client->deleteObject(array( |
138
|
|
|
'Bucket' => Configure::read('ContentsFile.Setting.S3.bucket'), |
139
|
|
|
'Key' => $filename, |
140
|
|
|
)); |
141
|
|
|
return true; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* deleteRecursive |
146
|
|
|
* S3上でのファイル削除(再帰的) |
147
|
|
|
* @author hagiwara |
148
|
|
|
*/ |
149
|
|
|
public function deleteRecursive($dirname) |
150
|
|
|
{ |
151
|
|
|
// $dirnameで消す単位は最低でもIDなので文字列内に数値のディレクトリがあることをチェックする |
152
|
|
|
if (!preg_match('#/[0-9]+/#', $dirname)) { |
153
|
|
|
return false; |
154
|
|
|
} |
155
|
|
|
$deleteFileLists = $this->getFileList($dirname); |
156
|
|
|
|
157
|
|
|
if (!empty($deleteFileLists)) { |
158
|
|
|
foreach ($deleteFileLists as $deleteDirInfo) { |
159
|
|
|
if (!$this->delete($deleteDirInfo['Key'])) { |
160
|
|
|
return false; |
161
|
|
|
} |
162
|
|
|
} |
163
|
|
|
} |
164
|
|
|
return true; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* move |
169
|
|
|
* S3上でのファイル移動(コピー&削除) |
170
|
|
|
* @author hagiwara |
171
|
|
|
*/ |
172
|
|
|
public function move($oldFilename, $newFilename) |
173
|
|
|
{ |
174
|
|
|
// 移動するファイルが存在しない |
175
|
|
|
if (!$this->fileExists($oldFilename)) { |
176
|
|
|
return false; |
177
|
|
|
} |
178
|
|
|
// 失敗時はException |
179
|
|
|
return $this->copy($oldFilename, $newFilename) && $this->delete($oldFilename); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* fileExists |
184
|
|
|
* S3上でのファイルの存在チェック(ディレクトリ存在チェックも兼) |
185
|
|
|
* @author hagiwara |
186
|
|
|
*/ |
187
|
|
|
public function fileExists($filename) |
188
|
|
|
{ |
189
|
|
|
return !empty($this->getFileList($filename)); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
/** |
193
|
|
|
* getFileList |
194
|
|
|
* 特定ディレクトリ内のfileの一覧取得 |
195
|
|
|
* @author hagiwara |
196
|
|
|
*/ |
197
|
|
|
public function getFileList($dirname) |
198
|
|
|
{ |
199
|
|
|
return $this->client->listObjects(array( |
200
|
|
|
'Bucket' => Configure::read('ContentsFile.Setting.S3.bucket'), |
201
|
|
|
'Prefix' => $dirname |
202
|
|
|
))->get('Contents'); |
203
|
|
|
} |
204
|
|
|
} |
205
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.