Verwendung des JetS3t-Java-Clients mit Amazon S3

Verwenden des JetS3t-Java-Clients mit Amazon S3

1. Überblick

In diesem Tutorial verwenden wir die BibliothekJetS3t mitAmazon S3.

Einfach ausgedrückt, erstellen wir Buckets, schreiben Daten in sie, lesen sie zurück, kopieren sie und listen sie dann auf und löschen sie.

2. JetS3t-Setup

2.1. Maven-Abhängigkeit

Zuerst müssen wir die NATS-Bibliothek undApache HttpClient zu unserenpom.xml hinzufügen:


    org.lucee
    jets3t
    0.9.4.0006L


    org.apache.httpcomponents
    httpclient
    4.5.5

Maven Central hat dielatest version of the JetS3t library und dielatest version of HttpClient. Die Quelle für JetS3t isthere.

Wir werdenApache Commons Codec für einen unserer Tests verwenden, also fügen wir das zu unserempom.xml -Stoo hinzu:


    org.lucee
    commons-codec
    1.10.L001

Maven Central hat die neueste Versionhere.

2.2. Amazon AWS-Schlüssel

We’ll need AWS Access Keys to connect to the S3 storage service. Es kann ein kostenloses Konto erstellt werdenhere.

Nachdem wir ein Konto haben, müssen wir eine Reihe vonsecurity keys. erstellen. Es gibt eine Dokumentation über Benutzer und verfügbare Zugriffsschlüsselhere.

JetS3t verwendet die Apache Commons-Protokollierung, daher verwenden wir sie auch, wenn wir Informationen über unsere Aktivitäten drucken möchten.

3. Verbindung zu einem einfachen Speicher herstellen

Nachdem wir nun einen AWS-Zugriffsschlüssel und einen geheimen Schlüssel haben, können wir eine Verbindung zum S3-Speicher herstellen.

3.1. Verbindung zu AWS herstellen

Zuerst erstellen wir AWS-Anmeldeinformationen und stellen anhand dieser Informationen eine Verbindung zum Service her:

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

RestS3Serviceis our connection to Amazon S3.It verwendetHttpClient, um über REST mit S3 zu kommunizieren.

3.2. Überprüfen der Verbindung

Wir können überprüfen, ob wir erfolgreich mit dem Dienst verbunden sind, indem wir Buckets auflisten:

S3Bucket[] myBuckets = s3Service.listAllBuckets();

Je nachdem, ob wir zuvor Buckets erstellt haben oder nicht, ist das Array möglicherweise leer. Wenn der Vorgang jedoch keine Ausnahme auslöst, besteht eine gültige Verbindung.

4. Buckets Management

Mit einer Verbindung zu Amazon S3 können wir Buckets erstellen, um unsere Daten zu speichern. S3 ist ein Objektspeichersystem. Daten werden als Objekte hochgeladen und in Buckets gespeichert.

Da alle S3-Buckets denselben globalen Namespace verwenden, muss jeder einen eindeutigen Namen haben.

4.1. Einen Eimer erstellen

Versuchen wir, einen Bucket-Namen "mybucket" zu erstellen:

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

Dies schlägt mit einer Ausnahme fehl:

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)

Der Name "mybucket" ist vorhersehbar bereits vergeben. Für den Rest des Tutorials werden wir unsere Namen zusammenstellen.

Versuchen wir es noch einmal mit einem anderen Namen:

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

Mit einem eindeutigen Namen ist der Anruf erfolgreich und es werden Informationen zu unserem Bucket angezeigt:

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

4.2. Einen Bucket löschen

Das Löschen eines Buckets ist bis auf eine Sache so einfach wie das Erstellen. buckets must be empty before they can be removed!

s3Service.deleteBucket("myuniquename");

Dies löst eine Ausnahme für einen nicht leeren Eimer aus.

4.3. Angeben der Bucket-Region

Buckets can be created in a specific data center.Für JetS3t ist der Standardwert Northern Virginia in den USA oder "us-east-1".

Wir können dies überschreiben, indem wir eine andere Region angeben:

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 verfügt über eine umfangreiche Liste von Regionen, die als Konstanten definiert sind.

5. Hochladen, Herunterladen und Löschen von Daten

Sobald wir einen Eimer haben, können wir ihm Objekte hinzufügen. Eimer sollen eine lange Lebensdauer haben und es gibt keine feste Grenze für die Größe oder Anzahl der Objekte, die ein Eimer enthalten kann.

Daten werden in S3 hochgeladen, indemS3Objects.We can upload data a from an InputStream,but JetS3t also provides convenience methods for Stringsand*Files*. erstellt werden

5.1. StringData

Schauen wir uns zuerstStringsan:

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

Ähnlich wie Buckets haben Objekte den Namenhowever, object names only live inside their buckets, so we don’t have to worry about them being globally unique.

Wir erstellen das Objekt, indem wir dem Konstruktor einen Namen und die Daten übergeben. Dann speichern wir es mitputObject.

Wenn wir diese Methode verwenden, umStringsmit JetS3t zu speichern, wird der richtige Inhaltstyp für uns festgelegt.

Fragen wir S3 nach Informationen zu unserem Objekt ab und sehen uns den Inhaltstyp an:

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

ObjectDetailsOnly()ruft die Objektmetadaten ab, ohne sie herunterzuladen. Wenn wir den Inhaltstyp protokollieren, sehen wir:

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

JetS3t identifizierte die Daten als Text und stellte die Länge für uns ein.

Laden Sie die Daten herunter und vergleichen Sie sie mit dem, was wir hochgeladen haben:

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));

Daten werden in derselbenS3Objectwe-Verwendung zum Hochladen abgerufen, wobei die verfügbaren Bytes inDataInputStream. verfügbar sind

5.2. Dateidaten

Der Vorgang zum Hochladen von Dateien ähneltStrings:

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

WennS3Objectsare einFile bestanden hat, leiten sie ihren Namen vom Basisnamen der Dateien ab, die sie enthalten:

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

JetS3t takes the File and uploads it for us. Es wird versucht, einmime.types file aus dem Klassenpfad zu laden und damit den Dateityp und den gesendeten Inhaltstyp entsprechend zu identifizieren.

Wenn wir die Objektinformationen unseres Datei-Uploads abrufen und den Inhaltstyp erhalten, sehen wir:

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

Laden Sie unsere Datei in eine neue herunter und vergleichen Sie den Inhalt:

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));

Ähnlich wieStringshat swe das Objekt heruntergeladen und mitDataInputStream eine neue Datei erstellt. Dann haben wir einen MD5-Hash für beide Dateien berechnet und verglichen.

5.3. Daten streamen

Wenn wir andere Objekte alsStringsoderFiles,hochladen, müssen Sie etwas mehr tun:

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);

Wir müssen vor dem Hochladen den Inhaltstyp und die Länge festlegen.

Das Abrufen dieses Streams bedeutet das Umkehren des Prozesses:

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));

Für verschiedene Datentypen kann mit der Content Type-Eigenschaft eine andere Methode zum Dekodieren des Objekts ausgewählt werden.

6. Kopieren, Verschieben und Umbenennen von Daten

6.1. Objekte kopieren

Objekte können in S3 kopiert werden, ohne sie abzurufen.

Kopieren Sie unsere Testdatei aus Abschnitt 5.2 und überprüfen Sie das Ergebnis:

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));

Wir können Objekte innerhalb desselben Buckets oder zwischen zwei verschiedenen kopieren.

Wenn das letzte Argument zutrifft, erhält das kopierte Objekt neue Metadaten. Andernfalls bleiben die Metadaten des Quellobjekts erhalten.

Wenn wir die Metadaten ändern möchten, können wir das Flag auf true setzen:

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

6.2. Objekte verschieben

Objects can be moved to another S3 bucket in the same region.Eine Verschiebeoperation ist eine Kopie und dann eine Löschoperation.

Wenn der Kopiervorgang fehlschlägt, wird das Quellobjekt nicht gelöscht. Wenn der Löschvorgang fehlschlägt, ist das Objekt sowohl im Quell- als auch im Zielspeicherort noch vorhanden.

Das Verschieben eines Objekts ähnelt dem Kopieren:

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

6.3. Objekte umbenennen

JetS3t has a convenience method for renaming objects. Um einen Objektnamen zu ändern, rufen wir ihn lediglich mit einem neuenS3Object auf:

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

7. Fazit

In diesem Tutorial verwendeten wir JetS3t, um eine Verbindung zu Amazon S3 herzustellen. Wir haben Eimer erstellt und gelöscht. Dann haben wir verschiedene Datentypen zu Buckets hinzugefügt und die Daten abgerufen. Zum Abschluss haben wir unsere Daten kopiert und verschoben.

Codebeispiele finden sich wie immer inover on GitHub.