Простая программа на Scala, работающая с Amazon S3
12 марта 2015
Несмотря на существование большого количества распределенных файловых систем (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
Метки: Scala, Облака, Функциональное программирование.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.