← На главную

Простая программа на Scala, работающая с Amazon S3

Несмотря на существование большого количества распределенных файловых систем (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:

Amazon S3 Endpoint

Название региона является частью endpoint и на скриншоте подчеркнуто красным. У меня регион называется «us-west-1», у вас он может быть таким же или чем-то похожим, в зависимости от региона, выбранного при создании бакета. Или, то же самое можно узнать еще проще, посмотрев внимательно на URL в строке браузера:

https://console.aws.amazon.com/s3/home?region=us-west-1

Для работы с S3 из Scala нам понадобится пользователь, обладающий соответствующими правами. В консоли AWS находим сервис IAM, создаем одного нового пользователя. После того, как пользователь будет создан, вы увидите примерно такую картину:

Новый пользователь, созданный через IAM

Сохраните где-нибудь Access Key ID и Secret Access Key, они нам скоро понадобятся.

В свойствах пользователя найдите раздел Managed Policies и нажмите Attach Policy. В списке находим полиси с именем AmazonS3FullAccess, ставим напротив него галку, жмем Attach Policy. Итак, у нас есть бакет в S3 и пользователь с полным доступом к сервису S3. Теперь можно и попрогать:

package me.eax.s3_example 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. Вывод программы:

Uploading /home/eax/temp/doge.jpg... Uploaded: https://s3-us-west-1.amazonaws.com/eaxme-test/xx/yy/doge.jpg Downloaded: /tmp/downloaded-doge.jpg

Можно проверить, что файл доступен по прямой ссылке для скачивания, что согласно консоли AWS он действительно находится в бакете с правильными правами, а также что скаченный файл ничем не отличается от закаченного. Вот, собственно, и все, никакой особой магии в работе с Amazon S3 нет. Сожалею, если разочаровал :)

Ссылки по теме:

А для каких целей вы используете Amazon S3? И не доводилось ли вам работать с другими распределенными файловыми системами?

Дополнение: Использование Elastic Load Balancer и Auto Scaling Groups