Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Paste
P2083
PhlabS3FileStorageEngine.php
Active
Public
Actions
Authored by
joshuaspence
on Dec 28 2017, 2:09 AM.
Edit Paste
Archive Paste
View Raw File
Subscribe
Mute Notifications
Award Token
Flag For Later
Tags
None
Referenced Files
F5342584: PhlabS3FileStorageEngine.php
Dec 28 2017, 2:09 AM
2017-12-28 02:09:02 (UTC+0)
Subscribers
None
<?php
/**
* This storage engine is similar to @{class:PhabricatorS3FileStorageEngine},
* but supports the use of
* [[http://docs.aws.amazon.com/STS/latest/UsingSTS/Welcome.html |
* IAM credentials]].
*
* This file engine uses [[http://aws.amazon.com/sdk-for-php/ | aws-sdk-php]]
* to interact with [[http://aws.amazon.com/ | Amazon Web Services]].
*
* @todo This class will be obsolete after https://secure.phabricator.com/T5155.
*/
final
class
PhlabS3FileStorageEngine
extends
PhabricatorFileStorageEngine
{
/**
* Return a unique string which identifies this storage engine.
*
* @return string Unique string for this engine.
*/
public
function
getEngineIdentifier
()
{
return
'aws-sdk'
;
}
/**
* Prioritize this engine relative to other engines.
*
* @return float
*/
public
function
getEnginePriority
()
{
return
100
;
}
/**
* Return `true` if the engine is currently writable.
*
* @return bool
*/
public
function
canWriteFiles
()
{
return
true
;
}
/**
* Return `true` if the engine has a filesize limit on storable files.
*
* @return bool
*/
public
function
hasFilesizeLimit
()
{
return
true
;
}
/**
* Writes file data into Amazon S3.
*
* Write file data to the backing storage and return a handle which can later
* be used to read or delete it.
*
* @param string The file data to write.
* @param map<string, wild> File metadata.
* @return string Unique string which identifies the stored file.
*/
public
function
writeFile
(
$data
,
array
$params
)
{
$s3
=
$this
->
getClient
();
// Generate a random name for this file. We add some directories to it
// (e.g. 'abcdef123456' becomes 'ab/cd/ef123456') to make large numbers of
// files more browsable with web/debugging tools like the S3 administration
// tool.
$seed
=
Filesystem
::
readRandomCharacters
(
20
);
$parts
=
[
substr
(
$seed
,
0
,
2
),
substr
(
$seed
,
2
,
2
),
substr
(
$seed
,
4
),
];
$name
=
implode
(
'/'
,
$parts
);
$s3_params
=
array
(
'Bucket'
=>
$this
->
getBucketName
(),
'Key'
=>
$name
,
'Body'
=>
$data
,
'ACL'
=>
'private'
,
'Metadata'
=>
[
'authorPHID'
=>
idx
(
$params
,
'authorPHID'
),
'isExplicitUpload'
=>
(
string
)
idx
(
$params
,
'isExplicitUpload'
),
'name'
=>
rawurlencode
(
idx
(
$params
,
'name'
)),
],
);
$mime_type
=
idx
(
$params
,
'mime-type'
);
if
(
$mime_type
)
{
$s3_params
[
'ContentType'
]
=
$mime_type
;
}
AphrontWriteGuard
::
willWrite
();
$profiler
=
PhutilServiceProfiler
::
getInstance
();
$call_id
=
$profiler
->
beginServiceCall
([
'type'
=>
's3'
,
'method'
=>
'putObject'
,
]);
$s3
->
putObject
(
$s3_params
);
$profiler
->
endServiceCall
(
$call_id
,
[]);
return
$name
;
}
/**
* Load a stored blob from Amazon S3.
*
* @param string The handle returned from @{method:writeFile} when the file
* was written.
* @return string File contents.
*/
public
function
readFile
(
$handle
)
{
$s3
=
$this
->
getClient
();
$profiler
=
PhutilServiceProfiler
::
getInstance
();
$call_id
=
$profiler
->
beginServiceCall
([
'type'
=>
's3'
,
'method'
=>
'getObject'
,
]);
$result
=
$s3
->
getObject
([
'Bucket'
=>
$this
->
getBucketName
(),
'Key'
=>
$handle
,
]);
$profiler
->
endServiceCall
(
$call_id
,
[]);
return
(
string
)
$result
[
'Body'
];
}
/**
* Delete a blob from Amazon S3.
*
* @param string The handle returned from @{method:writeFile} when the file
* was written.
* @return void
*/
public
function
deleteFile
(
$handle
)
{
$s3
=
$this
->
getClient
();
AphrontWriteGuard
::
willWrite
();
$profiler
=
PhutilServiceProfiler
::
getInstance
();
$call_id
=
$profiler
->
beginServiceCall
([
'type'
=>
's3'
,
'method'
=>
'deleteObject'
,
]);
$s3
->
deleteObject
([
'Bucket'
=>
$this
->
getBucketName
(),
'Key'
=>
$handle
,
]);
$profiler
->
endServiceCall
(
$call_id
,
[]);
}
/**
* Retrieve the S3 bucket name.
*
* @return string
*/
protected
function
getBucketName
()
{
$key
=
'storage.s3.bucket'
;
$bucket
=
PhabricatorEnv
::
getEnvConfig
(
$key
);
if
(!
$bucket
)
{
throw
new
PhabricatorFileStorageConfigurationException
(
pht
(
"No '%s' specified!"
,
$key
));
}
return
$bucket
;
}
/**
* Create a new S3 API object.
*
* @phutil-external-symbol class Aws\S3\S3Client
*/
protected
function
getClient
()
{
$region
=
PhabricatorEnv
::
getEnvConfig
(
'amazon-s3.region'
);
return
new
Aws\S3\S3Client
([
'region'
=>
$region
,
'version'
=>
'latest'
,
]);
}
}
Event Timeline
joshuaspence
created this paste.
Dec 28 2017, 2:09 AM
2017-12-28 02:09:02 (UTC+0)
joshuaspence
mentioned this in
T5155: Evaluate support for AWS IAM Roles in S3 Client
.
Log In to Comment