Несмотря на существование большого количества распределенных файловых систем (Riak CS, MongoDB GridFS, Cassandra File System, и прочих) многие продолжают отдавать свое предпочтение сервису Amazon S3. Что не удивительно, учитывая его гибкость, разумную стоимость, отсутствие необходимости самому что-либо администрировать и наличие могучего SDK. В этой заметке будет показано, как работать с Amazon S3 при помощи этого SDK на языке программирования Scala .
Прежде, чем перейти непосредственно к программированию, создадим небольшое тестовое окружение через консоль AWS . Находим в ней сервис S3, открываем, жмем «Create Bucket». От вас потребуется выбрать регион, в котором будет размещаться бакет, а также ввести имя бакета. Имена бакетов в S3 глобальны, поэтому не удивляйтесь, если имя «test-bucket» уже будет занято другим пользователем 🙂 Также в скором времени нам понадобится идентификатор выбранного региона. Откройте бакет, нажмите Properties (справа), найдите раздел Static Website Histing, а в нем — endpoint:
Название региона является частью endpoint и на скриншоте подчеркнуто красным. У меня регион называется «us-west-1», у вас он может быть таким же или чем-то похожим, в зависимости от региона, выбранного при создании бакета. Или, то же самое можно узнать еще проще, посмотрев внимательно на URL в строке браузера:
Для работы с S3 из Scala нам понадобится пользователь, обладающий соответствующими правами. В консоли AWS находим сервис IAM, создаем одного нового пользователя. После того, как пользователь будет создан, вы увидите примерно такую картину:
Сохраните где-нибудь Access Key ID и Secret Access Key, они нам скоро понадобятся.
В свойствах пользователя найдите раздел Managed Policies и нажмите Attach Policy. В списке находим полиси с именем AmazonS3FullAccess, ставим напротив него галку, жмем Attach Policy. Итак, у нас есть бакет в S3 и пользователь с полным доступом к сервису S3. Теперь можно и попрогать:
import com. amazonaws . _
import com. amazonaws . auth . _
import com. amazonaws . services . s3 . _
import com. amazonaws . services . s3 . model . _
import java. io . _
object AmazonS3Example extends App {
val accessKey = «AKIAJNSEFYYHD43JLEKQ»
val secretKey = «8c0NOloloTrololoOloloTrololoOloloTrololo»
val bucketName = «eaxme-test»
// вот где понадобилось имя региона:
val urlPrefix = «https://s3-us-west-1.amazonaws.com»
val credentials = new BasicAWSCredentials ( accessKey, secretKey )
val client = new AmazonS3Client ( credentials )
def uploadToS3 ( fileName : String, uploadPath : String ) : String = {
client. putObject ( bucketName, uploadPath, new File ( fileName ) )
val acl = client. getObjectAcl ( bucketName, uploadPath )
acl. grantPermission ( GroupGrantee. AllUsers , Permission. Read )
client. setObjectAcl ( bucketName, uploadPath, acl )
s «$urlPrefix/$bucketName/$uploadPath»
}
def fileIsUploadedToS3 ( uploadPath : String ) : Boolean = {
try {
client. getObjectMetadata ( bucketName, uploadPath )
true
} catch {
case e : AmazonServiceException if e. getStatusCode == 404 =>
false
}
}
def downloadFromS3 ( uploadPath : String, downloadPath : String ) {
if ( ! fileIsUploadedToS3 ( uploadPath ) ) {
throw new RuntimeException ( s «File $uploadPath is not uploaded!» )
}
client. getObject ( new GetObjectRequest ( bucketName, uploadPath ) ,
new File ( downloadPath ) )
}
if ( args. length < 2 ) {
println ( «Usage: prog.jar file.dat s3/upload/path.dat » +
«local/download/path.dat» )
} else {
val Array ( fileName, uploadPath, downloadPath, _* ) = args
println ( s «Uploading $fileName…» )
val url = uploadToS3 ( fileName, uploadPath )
println ( s «Uploaded: $url» )
downloadFromS3 ( uploadPath, downloadPath )
println ( s «Downloaded: $downloadPath» )
}
}
Эта программа закачивает заданный файл в S3, а затем скачивает его обратно. Как видите, все довольно просто — заводится клиент, у клиента есть методы getObject и putObject. По умолчанию файлы, залитые в S3, недоступны извне по прямой ссылке. Поэтому в данном примере мы явно проставляем права доступа к файлу с помощью метода setObjectAcl. Вывод программы:
Uploaded: https://s3-us-west-1.amazonaws.com/eaxme-test/xx/yy/doge.jpg
Downloaded: /tmp/downloaded-doge.jpg
Можно проверить, что файл доступен по прямой ссылке для скачивания, что согласно консоли AWS он действительно находится в бакете с правильными правами, а также что скаченный файл ничем не отличается от закаченного. Вот, собственно, и все, никакой особой магии в работе с Amazon S3 нет. Сожалею, если разочаровал 🙂
Ссылки по теме:
- Javadoc по классу AmazonS3Client ;
- S3Sample.java из исходников AWS Java SDK ;
- Пример работы с S3 в репозитории awslabs/aws-java-sample ;
- Исходники к этой заметке на GitHub ;
А для каких целей вы используете Amazon S3? И не доводилось ли вам работать с другими распределенными файловыми системами?
Дополнение: Использование Elastic Load Balancer и Auto Scaling Groups