Использование 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.