Использование JetS3t Java-клиента с Amazon S3

Использование Java-клиента JetS3t с Amazon S3

1. обзор

В этом руководстве мы будем использовать библиотекуJetS3t сAmazon S3.

Проще говоря, мы создадим корзины, запишем в них данные, прочитаем данные, скопируем их, а затем составим список и удалим их.

2. JetS3t Настройка

2.1. Maven Dependency

Во-первых, нам нужно добавить библиотеку NATS иApache HttpClient в нашpom.xml:


    org.lucee
    jets3t
    0.9.4.0006L


    org.apache.httpcomponents
    httpclient
    4.5.5

В Maven Central естьlatest version of the JetS3t library иlatest version of HttpClient. Источник для JetS3t можно найтиhere.

Мы будем использоватьApache Commons Codec для одного из наших тестов, поэтому добавим его в нашpom.xml too:


    org.lucee
    commons-codec
    1.10.L001

В Maven Central установлена ​​последняя версияhere.

2.2. Ключи Amazon AWS

We’ll need AWS Access Keys to connect to the S3 storage service. Можно создать бесплатную учетную записьhere.

После того, как у нас есть учетная запись, нам нужно создать наборsecurity keys.. Есть документация о пользователях и доступных ключах доступаhere.

JetS3 не использует ведение журнала Apache Commons, поэтому мы тоже будем использовать его, когда хотим распечатать информацию о том, что мы делаем.

3. Подключение к простому хранилищу

Теперь, когда у нас есть ключ доступа AWS и секретный ключ, мы можем подключиться к хранилищу S3.

3.1. Подключение к AWS

Сначала мы создаем учетные данные AWS, а затем используем их для подключения к сервису:

AWSCredentials awsCredentials
  = new AWSCredentials("access key", "secret key");
s3Service = new RestS3Service(awsCredentials);

RestS3Serviceis our connection to Amazon S3. Он используетHttpClientto для связи с S3 через REST.

3.2. Проверка соединения

Мы можем проверить, что мы успешно подключились к сервису, перечислив сегменты:

S3Bucket[] myBuckets = s3Service.listAllBuckets();

В зависимости от того, создавали ли мы ранее сегменты или нет, массив может быть пустым, но если операция не вызывает исключения, у нас есть действительное соединение.

4. Управление ведрами

При подключении к Amazon S3 мы можем создавать сегменты для хранения наших данных. S3 - система хранения объектов. Данные загружаются как объекты и хранятся в контейнерах.

Поскольку все сегменты S3 используют одно и то же глобальное пространство имен, каждое из них должно иметь уникальное имя.

4.1. Создание ведра

Давайте попробуем создать сегмент с именем «mybucket»:

S3Bucket bucket = s3Service.createBucket("mybucket");

Это терпит неудачу с исключением:

org.jets3t.service.S3ServiceException: Service Error Message.
  -- ResponseCode: 409, ResponseStatus: Conflict, XML Error Message:
  
  BucketAlreadyExists The requested bucket name is not available.
  The bucket namespace is shared by all users of the system.
  Please select a different name and try again.
  mybucket 07BE34FF3113ECCF
at org.jets3t.service.S3Service.createBucket(S3Service.java:1586)

Имя «mybucket», как и ожидалось, уже занято. В оставшейся части урока мы придумаем имена.

Попробуем еще раз с другим именем:

S3Bucket bucket = s3Service.createBucket("myuniquename");
log.info(bucket);

С уникальным именем вызов завершается успешно, и мы видим информацию о нашем сегменте:

[INFO] JetS3tClient - S3Bucket
[name=myuniquename,location=US,creationDate=Sat Mar 31 16:47:47 EDT 2018,owner=null]

4.2. Удаление корзины

Удалить ведро так же просто, как его создать, за исключением одного момента; buckets must be empty before they can be removed!с

s3Service.deleteBucket("myuniquename");

Это вызовет исключение для корзины, которая не является пустой.

4.3. Указание области сегмента

Buckets can be created in a specific data center.Для JetS3t по умолчанию используется Северная Вирджиния в США или «us-east-1».

Мы можем переопределить это, указав другой регион:

S3Bucket euBucket
  = s3Service.createBucket("eu-bucket", S3Bucket.LOCATION_EUROPE);
S3Bucket usWestBucket = s3Service
  .createBucket("us-west-bucket", S3Bucket.LOCATION_US_WEST);
S3Bucket asiaPacificBucket = s3Service
  .createBucket("asia-pacific-bucket", S3Bucket.LOCATION_ASIA_PACIFIC);

JetS3t имеет обширный список областей, определенных как константы.

5. Выгрузка, загрузка и удаление данных

Как только у нас есть корзина, мы можем добавить к ней объекты. Ковши рассчитаны на длительный срок службы, и жестких ограничений на размер или количество объектов, которые может содержать ведро, не существует.

Данные загружаются в S3 путем созданияS3Objects.We can upload data a from an InputStream,but JetS3t also provides convenience methods for Stringsand*Files*.

5.1. StringДанные

Давайте сначала посмотрим наStrings:

S3Object stringObject = new S3Object("object name", "string object");
s3Service.putObject("myuniquebucket", stringObject);

Подобно ведрам, объекты имеют имена,however, object names only live inside their buckets, so we don’t have to worry about them being globally unique.

Мы создаем объект, передавая имя и данные конструктору. Затем мы сохраняем его с помощьюputObject.

Когда мы используем этот метод для храненияStringsw с JetS3t, он устанавливает для нас правильный тип содержимого.

Давайте запросим у S3 информацию о нашем объекте и посмотрим на тип контента:

StorageObject objectDetailsOnly
  = s3Service.getObjectDetails("myuniquebucket", "my string");
log.info("Content type: " + objectDetailsOnly.getContentType() + " length: "
  + objectDetailsOnly.getContentLength());

ObjectDetailsOnly()извлекает метаданные объектов, не загружая их. Когда мы регистрируем тип контента, мы видим:

[INFO] JetS3tClient - Content type: text/plain; charset=utf-8 length: 9

JetS3t идентифицировал данные как текст и установил длину для нас.

Давайте загрузим данные и сравним их с тем, что мы загрузили:

S3Object downloadObject =
  s3Service.getObject("myuniquebucket, "string object");
String downloadString = new BufferedReader(new InputStreamReader(
  object.getDataInputStream())).lines().collect(Collectors.joining("\n"));

assertTrue("string object".equals(downloadString));

Данные извлекаются в том жеS3Object, используемом для их загрузки, а байты доступны вDataInputStream.

5.2. Данные файла

Процесс загрузки файлов аналогиченStrings:

File file = new File("src/test/resources/test.jpg");
S3Object fileObject = new S3Object(file);
s3Service.putObject("myuniquebucket", fileObject);

КогдаS3Objects передаетсяFile, они получают свое имя из базового имени файлов, которые они содержат:

[INFO] JetS3tClient - File object name is test.jpg

JetS3t takes the File and uploads it for us. Он попытается загрузитьmime.types file из пути к классам и использовать его для определения типа файла и отправленного типа содержимого.

Если мы извлекаем информацию об объекте загрузки нашего файла и получаем тип контента, который мы видим:

[INFO] JetS3tClient - Content type:application/octet-stream

Давайте загрузим наш файл в новый и сравним его содержимое:

String getFileMD5(String filename) throws IOException {
    try (FileInputStream fis = new FileInputStream(new File(filename))) {
        return DigestUtils.md5Hex(fis);
    }
}

S3Object fileObject = s3Service.getObject("myuniquebucket", "test.jpg");
File newFile = new File("/tmp/newtest.jpg");
Files.copy(fileObject.getDataInputStream(), newFile.toPath(),
  StandardCopyOption.REPLACE_EXISTING);
String origMD5 = getFileMD5("src/test/resources/test.jpg");
String newMD5 = getFileMD5("src/test/resources/newtest.jpg");
assertTrue(origMD5.equals(newMD5));

ПодобноStringswe загрузил объект и использовалDataInputStream для создания нового файла. Затем мы вычислили хеш MD5 для обоих файлов и сравнили их.

5.3. Потоковые данные

Когда мы загружаем объекты, отличные отStringsorFiles,, у Swe есть немного больше работы:

ArrayList numbers = new ArrayList<>();
// adding elements to the ArrayList

ByteArrayOutputStream bytes = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(bytes);
objectOutputStream.writeObject(numbers);

ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes.toByteArray());

S3Object streamObject = new S3Object("stream");
streamObject.setDataInputStream(byteArrayInputStream);
streamObject.setContentLength(byteArrayInputStream.available());
streamObject.setContentType("binary/octet-stream");

s3Service.putObject(BucketName, streamObject);

Нам нужно установить тип и длину нашего контента перед загрузкой.

Извлечение этого потока означает реверсирование процесса:

S3Object newStreamObject = s3Service.getObject(BucketName, "stream");

ObjectInputStream objectInputStream = new ObjectInputStream(
  newStreamObject.getDataInputStream());
ArrayList newNumbers = (ArrayList) objectInputStream
  .readObject();

assertEquals(2, (int) newNumbers.get(0));
assertEquals(3, (int) newNumbers.get(1));
assertEquals(5, (int) newNumbers.get(2));
assertEquals(7, (int) newNumbers.get(3));

Для разных типов данных свойство типа контента может использоваться для выбора другого метода для декодирования объекта.

6. Копирование, перемещение и переименование данных

6.1. Копирование объектов

Объекты можно копировать внутри S3, не извлекая их.

Давайте скопируем наш тестовый файл из раздела 5.2 и проверим результат:

S3Object targetObject = new S3Object("testcopy.jpg");
s3Service.copyObject(
  BucketName, "test.jpg",
  "myuniquebucket", targetObject, false);
S3Object newFileObject = s3Service.getObject(
  "myuniquebucket", "testcopy.jpg");

File newFile = new File("src/test/resources/testcopy.jpg");
Files.copy(
  newFileObject.getDataInputStream(),
  newFile.toPath(),
  REPLACE_EXISTING);
String origMD5 = getFileMD5("src/test/resources/test.jpg");
String newMD5 = getFileMD5("src/test/resources/testcopy.jpg");

assertTrue(origMD5.equals(newMD5));

Мы можем копировать объекты внутри одного блока или между двумя различными.

Если последний аргумент равен true, скопированный объект получит новые метаданные. В противном случае он сохранит метаданные исходного объекта.

Если мы хотим изменить метаданные, мы можем установить флаг в true:

targetObject = new S3Object("testcopy.jpg");
targetObject.addMetadata("My_Custom_Field", "Hello, World!");
s3Service.copyObject(
  "myuniquebucket", "test.jpg",
  "myuniquebucket", targetObject, true);

6.2. Движущиеся объекты

Objects can be moved to another S3 bucket in the same region. Операция перемещения - это копирование, а затем операция удаления.

В случае сбоя операции копирования исходный объект не удаляется. Если операция удаления не удалась, объект все еще будет существовать в источнике, а также в месте назначения.

Перемещение объекта похоже на его копирование:

s3Service.moveObject(
  "myuniquebucket",
  "test.jpg",
  "myotheruniquebucket",
  new S3Object("spidey.jpg"),
  false);

6.3. Переименование объектов

JetS3t has a convenience method for renaming objects. Чтобы изменить имя объекта, мы просто вызываем его с новымS3Object:

s3Service.renameObject(
  "myuniquebucket", "test.jpg", new S3Object("spidey.jpg"));

7. Заключение

В этом руководстве мы использовали JetS3t для подключения к Amazon S3. Мы создали и удалили ведра. Затем мы добавили разные типы данных в ведра и получили данные. Чтобы подвести итоги, мы скопировали и перенесли наши данные.

Примеры кода, как всегда, можно найтиover on GitHub.