View a markdown version of this page

Arbeite mit Amazon S3 vorsignierte URLs - AWS SDK for Java 2.x

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Arbeite mit Amazon S3 vorsignierte URLs

Pre-signed URLs bieten temporären Zugriff auf private S3-Objekte, ohne dass Benutzer über AWS Anmeldeinformationen oder Berechtigungen verfügen müssen.

Angenommen, Alice hat Zugriff auf ein S3-Objekt, und sie möchte den Zugriff auf dieses Objekt vorübergehend mit Bob teilen. Alice kann eine vorsignierte GET-Anfrage generieren, um sie mit Bob zu teilen, sodass er das Objekt herunterladen kann, ohne Zugriff auf Alices Anmeldeinformationen zu benötigen. Sie können vorsignierte URLs für HTTP GET- und für HTTP PUT-Anfragen generieren.

Generieren Sie eine vorsignierte URL für ein Objekt und laden Sie es dann herunter (GET-Anfrage)

Das folgende Beispiel besteht aus zwei Teilen.

  • Teil 1: Alice generiert die vorsignierte URL für ein Objekt.

  • Teil 2: Bob lädt das Objekt mithilfe der vorsignierten URL herunter.

Teil 1: Generieren Sie die URL

Alice hat bereits ein Objekt in einem S3-Bucket. Sie verwendet den folgenden Code, um eine URL-Zeichenfolge zu generieren, die Bob in einer nachfolgenden GET-Anfrage verwenden kann.

import com.example.s3.util.PresignUrlUtils; import org.slf4j.Logger; import software.amazon.awssdk.http.HttpExecuteRequest; import software.amazon.awssdk.http.HttpExecuteResponse; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.S3Exception; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest; import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest; import software.amazon.awssdk.utils.IoUtils; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.file.Paths; import java.time.Duration; import java.util.UUID;
/* Create a pre-signed URL to download an object in a subsequent GET request. */ public String createPresignedGetUrl(String bucketName, String keyName) { try (S3Presigner presigner = S3Presigner.create()) { GetObjectRequest objectRequest = GetObjectRequest.builder() .bucket(bucketName) .key(keyName) .build(); GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) // The URL will expire in 10 minutes. .getObjectRequest(objectRequest) .build(); PresignedGetObjectRequest presignedRequest = presigner.presignGetObject(presignRequest); logger.info("Presigned URL: [{}]", presignedRequest.url().toString()); logger.info("HTTP method: [{}]", presignedRequest.httpRequest().method()); return presignedRequest.url().toExternalForm(); } }

Teil 2: Laden Sie das Objekt herunter

Bob verwendet eine der folgenden Codeoptionen, um das Objekt herunterzuladen. Alternativ könnte er einen Browser verwenden, um die GET-Anfrage auszuführen.

/* Use the JDK HttpURLConnection (since v1.1) class to do the download. */ public byte[] useHttpUrlConnectionToGet(String presignedUrlString) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // Capture the response body to a byte array. try { URL presignedUrl = new URL(presignedUrlString); HttpURLConnection connection = (HttpURLConnection) presignedUrl.openConnection(); connection.setRequestMethod("GET"); // Download the result of executing the request. try (InputStream content = connection.getInputStream()) { IoUtils.copy(content, byteArrayOutputStream); } logger.info("HTTP response code is " + connection.getResponseCode()); } catch (S3Exception | IOException e) { logger.error(e.getMessage(), e); } return byteArrayOutputStream.toByteArray(); }
/* Use the JDK HttpClient (since v11) class to do the download. */ public byte[] useHttpClientToGet(String presignedUrlString) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // Capture the response body to a byte array. HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(); HttpClient httpClient = HttpClient.newHttpClient(); try { URL presignedUrl = new URL(presignedUrlString); HttpResponse<InputStream> response = httpClient.send(requestBuilder .uri(presignedUrl.toURI()) .GET() .build(), HttpResponse.BodyHandlers.ofInputStream()); IoUtils.copy(response.body(), byteArrayOutputStream); logger.info("HTTP response code is " + response.statusCode()); } catch (URISyntaxException | InterruptedException | IOException e) { logger.error(e.getMessage(), e); } return byteArrayOutputStream.toByteArray(); }
/* Use the AWS SDK for Java SdkHttpClient class to do the download. */ public byte[] useSdkHttpClientToGet(String presignedUrlString) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // Capture the response body to a byte array. try { URL presignedUrl = new URL(presignedUrlString); SdkHttpRequest request = SdkHttpRequest.builder() .method(SdkHttpMethod.GET) .uri(presignedUrl.toURI()) .build(); HttpExecuteRequest executeRequest = HttpExecuteRequest.builder() .request(request) .build(); try (SdkHttpClient sdkHttpClient = ApacheHttpClient.create()) { HttpExecuteResponse response = sdkHttpClient.prepareRequest(executeRequest).call(); response.responseBody().ifPresentOrElse( abortableInputStream -> { try { IoUtils.copy(abortableInputStream, byteArrayOutputStream); } catch (IOException e) { throw new RuntimeException(e); } }, () -> logger.error("No response body.")); logger.info("HTTP Response code is {}", response.httpResponse().statusCode()); } } catch (URISyntaxException | IOException e) { logger.error(e.getMessage(), e); } return byteArrayOutputStream.toByteArray(); }

Der AWS SDK for Java 2.x bietet eine vorsignierte URL-Erweiterung, mit der Objekte mithilfe einer vorsignierten URL über S3AsyncClient die asynchrone SDK-Pipeline heruntergeladen werden. Greifen Sie mit auf die Erweiterung zu. S3AsyncClient.presignedUrlExtension() Diese Funktion ist in der SDK-Version 2.48.0 und höher verfügbar.

Einschränkung des CRT-Clients

Der AWS CRT-based S3-Client (S3AsyncClient.crtBuilder()) unterstützt derzeit die vorsignierte URL-Erweiterung nicht. Verwenden Sie stattdessen S3AsyncClient.builder().

Anforderung im Prüfsummenmodus

Um die Datenintegrität zu überprüfen, aktivieren checksumMode(ChecksumMode.ENABLED) Sie das, GetObjectRequest wenn Sie die vorsignierte URL generieren. Geben Sie den Prüfsummenmodus beim Vorsignieren an. Sie können es später nicht hinzufügen, wenn Sie den Download ausführen. Wenn Sie die S3AsyncClient vorsignierte URL-Erweiterung verwenden, sendet das SDK automatisch den erforderlichen x-amz-checksum-mode Header.

import java.nio.file.Paths; import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest;
In eine Datei oder in Byte herunterladen
Download to file
S3AsyncClient s3AsyncClient = S3AsyncClient.builder() .region(Region.US_EAST_1) .build(); GetObjectResponse response = s3AsyncClient.presignedUrlExtension() .getObject( PresignedUrlDownloadRequest.builder() .presignedUrl(presignedGetObjectRequest.url()) .build(), Paths.get("/tmp/downloaded-file.bin")) .join(); // Or use the consumer builder pattern GetObjectResponse response = s3AsyncClient.presignedUrlExtension() .getObject( r -> r.presignedUrl(presignedGetObjectRequest.url()), Paths.get("/tmp/downloaded-file.bin")) .join();
Download to bytes
S3AsyncClient s3AsyncClient = S3AsyncClient.builder() .region(Region.US_EAST_1) .build(); ResponseBytes<GetObjectResponse> bytes = s3AsyncClient.presignedUrlExtension() .getObject( PresignedUrlDownloadRequest.builder() .presignedUrl(presignedGetObjectRequest.url()) .build(), AsyncResponseTransformer.toBytes()) .join(); // Or use the consumer builder pattern ResponseBytes<GetObjectResponse> bytes = s3AsyncClient.presignedUrlExtension() .getObject( r -> r.presignedUrl(presignedGetObjectRequest.url()), AsyncResponseTransformer.toBytes()) .join();
Mehrteiliger Download für große Dateien

Um große Objekte parallel herunterzuladen, stellen Sie multipartEnabled(true) auf dem Client Folgendes ein:

Download to file
S3AsyncClient multipartClient = S3AsyncClient.builder() .region(Region.US_EAST_1) .multipartEnabled(true) .multipartConfiguration(c -> c.minimumPartSizeInBytes(8 * 1024 * 1024L)) .build(); GetObjectResponse response = multipartClient.presignedUrlExtension() .getObject( PresignedUrlDownloadRequest.builder() .presignedUrl(presignedGetObjectRequest.url()) .build(), Paths.get("/tmp/large-file.bin")) .join();
Download to bytes
S3AsyncClient multipartClient = S3AsyncClient.builder() .region(Region.US_EAST_1) .multipartEnabled(true) .multipartConfiguration(c -> c.minimumPartSizeInBytes(8 * 1024 * 1024L)) .build(); ResponseBytes<GetObjectResponse> bytes = multipartClient.presignedUrlExtension() .getObject( PresignedUrlDownloadRequest.builder() .presignedUrl(presignedGetObjectRequest.url()) .build(), AsyncResponseTransformer.toBytes()) .join();
Verwenden Sie den Amazon S3 Transfer Manager

Mit dem Amazon S3 Transfer Manager können Sie Objekte mithilfe vorsignierter URLs herunterladen und den Fortschritt verfolgen. TransferListener

Fügen Sie das s3-transfer-manager Artefakt zu Ihrem Projekt hinzu:

<dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>bom</artifactId> <version>2.48.01</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3-transfer-manager</artifactId> </dependency> </dependencies>

1 Die neueste BOM-Version finden Sie im Maven Central Repository.

import java.nio.file.Paths; import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; import software.amazon.awssdk.transfer.s3.S3TransferManager; import software.amazon.awssdk.transfer.s3.model.CompletedFileDownload; import software.amazon.awssdk.transfer.s3.model.Download; import software.amazon.awssdk.transfer.s3.model.PresignedDownloadFileRequest; import software.amazon.awssdk.transfer.s3.model.PresignedDownloadRequest; import software.amazon.awssdk.transfer.s3.model.PresignedFileDownload; import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener;
Download to file
S3TransferManager transferManager = S3TransferManager.create(); PresignedFileDownload fileDownload = transferManager.downloadFileWithPresignedUrl( PresignedDownloadFileRequest.builder() .presignedUrlDownloadRequest(PresignedUrlDownloadRequest.builder() .presignedUrl(presignedGetObjectRequest.url()) .build()) .destination(Paths.get("/tmp/transfer-download.bin")) .addTransferListener(LoggingTransferListener.create()) .build()); CompletedFileDownload completed = fileDownload.completionFuture().join();
Download to bytes
S3TransferManager transferManager = S3TransferManager.create(); Download<ResponseBytes<GetObjectResponse>> bytesDownload = transferManager.downloadWithPresignedUrl( PresignedDownloadRequest.<ResponseBytes<GetObjectResponse>>builder() .presignedUrlDownloadRequest(PresignedUrlDownloadRequest.builder() .presignedUrl(presignedGetObjectRequest.url()) .build()) .responseTransformer(AsyncResponseTransformer.toBytes()) .addTransferListener(LoggingTransferListener.create()) .build()); ResponseBytes<GetObjectResponse> result = bytesDownload.completionFuture().join().result();
Pause und Wiederaufnahme werden nicht unterstützt

Im Gegensatz zu regulären FileDownload Versionen werden Pause und Wiederaufnahme PresignedFileDownload nicht unterstützt, da vorsignierte URLs bei einer unterbrochenen Übertragung ablaufen können.

Weitere Informationen zum Amazon S3 Transfer Manager, einschließlich Konfigurationsoptionen und zusätzlicher Beispiele, finden Sie unter. Dateien und Verzeichnisse mit dem Amazon S3 Transfer Manager übertragen

Sehen Sie sich das vollständige Beispiel an und testen Sie es weiter GitHub.

Generieren Sie eine vorsignierte URL für einen Upload und laden Sie dann eine Datei hoch (PUT-Anfrage)

Das folgende Beispiel besteht aus zwei Teilen.

  • Teil 1: Alice generiert die vorsignierte URL, um ein Objekt hochzuladen.

  • Teil 2: Bob lädt eine Datei mithilfe der vorsignierten URL hoch.

Teil 1: Generieren Sie die URL

Alice hat bereits einen S3-Bucket. Sie verwendet den folgenden Code, um eine URL-Zeichenfolge zu generieren, die Bob in einer nachfolgenden PUT-Anfrage verwenden kann.

import com.example.s3.util.PresignUrlUtils; import org.slf4j.Logger; import software.amazon.awssdk.core.internal.sync.FileContentStreamProvider; import software.amazon.awssdk.http.HttpExecuteRequest; import software.amazon.awssdk.http.HttpExecuteResponse; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.S3Exception; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest; import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; import java.util.Map; import java.util.UUID;
/* Create a presigned URL to use in a subsequent PUT request */ public String createPresignedUrl(String bucketName, String keyName, Map<String, String> metadata) { try (S3Presigner presigner = S3Presigner.create()) { PutObjectRequest objectRequest = PutObjectRequest.builder() .bucket(bucketName) .key(keyName) .metadata(metadata) .build(); PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) // The URL expires in 10 minutes. .putObjectRequest(objectRequest) .build(); PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest); String myURL = presignedRequest.url().toString(); logger.info("Presigned URL to upload a file to: [{}]", myURL); logger.info("HTTP method: [{}]", presignedRequest.httpRequest().method()); return presignedRequest.url().toExternalForm(); } }

Teil 2: Laden Sie ein Dateiobjekt hoch

Bob verwendet eine der folgenden drei Codeoptionen, um eine Datei hochzuladen.

/* Use the JDK HttpURLConnection (since v1.1) class to do the upload. */ public void useHttpUrlConnectionToPut(String presignedUrlString, File fileToPut, Map<String, String> metadata) { logger.info("Begin [{}] upload", fileToPut.toString()); try { URL presignedUrl = new URL(presignedUrlString); HttpURLConnection connection = (HttpURLConnection) presignedUrl.openConnection(); connection.setDoOutput(true); metadata.forEach((k, v) -> connection.setRequestProperty("x-amz-meta-" + k, v)); connection.setRequestMethod("PUT"); OutputStream out = connection.getOutputStream(); try (RandomAccessFile file = new RandomAccessFile(fileToPut, "r"); FileChannel inChannel = file.getChannel()) { ByteBuffer buffer = ByteBuffer.allocate(8192); //Buffer size is 8k while (inChannel.read(buffer) > 0) { buffer.flip(); for (int i = 0; i < buffer.limit(); i++) { out.write(buffer.get()); } buffer.clear(); } } catch (IOException e) { logger.error(e.getMessage(), e); } out.close(); connection.getResponseCode(); logger.info("HTTP response code is " + connection.getResponseCode()); } catch (S3Exception | IOException e) { logger.error(e.getMessage(), e); } }
/* Use the JDK HttpClient (since v11) class to do the upload. */ public void useHttpClientToPut(String presignedUrlString, File fileToPut, Map<String, String> metadata) { logger.info("Begin [{}] upload", fileToPut.toString()); HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(); metadata.forEach((k, v) -> requestBuilder.header("x-amz-meta-" + k, v)); HttpClient httpClient = HttpClient.newHttpClient(); try { final HttpResponse<Void> response = httpClient.send(requestBuilder .uri(new URL(presignedUrlString).toURI()) .PUT(HttpRequest.BodyPublishers.ofFile(Path.of(fileToPut.toURI()))) .build(), HttpResponse.BodyHandlers.discarding()); logger.info("HTTP response code is " + response.statusCode()); } catch (URISyntaxException | InterruptedException | IOException e) { logger.error(e.getMessage(), e); } }
/* Use the AWS SDK for Java V2 SdkHttpClient class to do the upload. */ public void useSdkHttpClientToPut(String presignedUrlString, File fileToPut, Map<String, String> metadata) { logger.info("Begin [{}] upload", fileToPut.toString()); try { URL presignedUrl = new URL(presignedUrlString); SdkHttpRequest.Builder requestBuilder = SdkHttpRequest.builder() .method(SdkHttpMethod.PUT) .uri(presignedUrl.toURI()); // Add headers metadata.forEach((k, v) -> requestBuilder.putHeader("x-amz-meta-" + k, v)); // Finish building the request. SdkHttpRequest request = requestBuilder.build(); HttpExecuteRequest executeRequest = HttpExecuteRequest.builder() .request(request) .contentStreamProvider(new FileContentStreamProvider(fileToPut.toPath())) .build(); try (SdkHttpClient sdkHttpClient = ApacheHttpClient.create()) { HttpExecuteResponse response = sdkHttpClient.prepareRequest(executeRequest).call(); logger.info("Response code: {}", response.httpResponse().statusCode()); } } catch (URISyntaxException | IOException e) { logger.error(e.getMessage(), e); } }

Sehen Sie sich das vollständige Beispiel an und testen Sie es weiter GitHub.

Fügen Sie Anforderungsfelder als URL-Abfrageparameter ein

Einige Anforderungsfelder sind HTTP-Headern GetObjectRequest und PutObjectRequest nicht URL-Abfrageparametern zugeordnet. Zum Beispiel,, requestPayer acl metadataserverSideEncryption, und storageClass Mapping zu x-amz-* Headern. Wenn Sie eine Anfrage vorab signieren, die eines dieser Felder festlegt, deckt die Signatur die Header ab. Die vorsignierte URL, die S3Presigner zurückgibt, enthält jedoch nicht die Header-Werte.

Der Aufrufer der vorsignierten URL muss dieselben Header mit der Anfrage senden. x-amz-* Andernfalls kehrt Amazon S3 zurück. SignatureDoesNotMatch HTTP-Clients, die benutzerdefinierte Header festlegen können, senden diese Header direkt. Die zuvor gezeigten SdkHttpClient BeispieleHttpURLConnection,HttpClient, und tun dies beispielsweise alle. Wenn der Anrufer jedoch keine benutzerdefinierten Header festlegen kann, schlägt die Anfrage fehl. Zu den gängigen Beispielen gehören ein Webbrowser, der die URL als Link öffnet, ein HTML-Formular, das direkt auf Amazon S3 hochgeladen wird, und jeder HTTP-Client, der die URL nur als Eingabe empfängt.

Damit die URL ohne zusätzliche Header funktioniert, übergeben Sie den Wert als signierten Abfrageparameter, anstatt das eingegebene Feld festzulegen. Verwenden Sie put on RawQueryParameter. AwsRequestOverrideConfiguration

Pre-sign eine GET-Anfrage mit requester-pays

Das folgende Beispiel generiert eine vorsignierte URL für eine GetObjectRequest mit der Einstellung requester-pays. Da der Wert ein Abfrageparameter ist, kann jeder Anrufer die URL verwenden, ohne einen Header zu senden. x-amz-request-payer

try (S3Presigner presigner = S3Presigner.create()) { GetObjectRequest getObjectRequest = GetObjectRequest.builder() .bucket("amzn-s3-demo-bucket") .key("example-key") .overrideConfiguration(o -> o.putRawQueryParameter("x-amz-request-payer", "requester")) .build(); GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) .getObjectRequest(getObjectRequest) .build(); PresignedGetObjectRequest presigned = presigner.presignGetObject(presignRequest); logger.info("Pre-signed URL: [{}]", presigned.url()); // Confirm the URL requires no headers at request time: logger.info("Signed headers: {}", presigned.signedHeaders().keySet()); // [host] }

Pre-sign eine PUT-Anfrage mit Metadaten

Das folgende Beispiel generiert eine vorsignierte URL für a PutObjectRequest mit zwei Metadatenwerten als signierte Abfrageparameter. Da es sich bei den Werten um Abfrageparameter handelt, kann jeder Anrufer die URL verwenden, ohne Header zu sendenx-amz-meta-*.

try (S3Presigner presigner = S3Presigner.create()) { PutObjectRequest putObjectRequest = PutObjectRequest.builder() .bucket("amzn-s3-demo-bucket") .key("example-key") .overrideConfiguration(o -> o .putRawQueryParameter("x-amz-meta-author", "alice") .putRawQueryParameter("x-amz-meta-purpose", "demo")) .build(); PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) .putObjectRequest(putObjectRequest) .build(); PresignedPutObjectRequest presigned = presigner.presignPutObject(presignRequest); logger.info("Pre-signed URL: [{}]", presigned.url()); // Confirm the URL requires no headers at upload time: logger.info("Signed headers: {}", presigned.signedHeaders().keySet()); // [host] }

Pre-sign eine PUT-Anfrage und das Hochladen einer Datei

Das folgende Beispiel zeigt den vollständigen Arbeitsablauf: eine Methode, die eine PUT-Anfrage mit allen x-amz-* Namen und Werten, die Sie als Map angeben, vorab signiert, und eine Methode, mit der die Datei hochgeladen wird. SdkHttpClient Da die Werte bereits Teil der signierten URL sind, legt die Upload-Methode keine Header fest. x-amz-* Im Gegensatz dazu legen die früheren Upload-Beispiele x-amz-meta-* Header explizit fest.

import com.example.s3.util.PresignUrlUtils; import org.slf4j.Logger; import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.core.internal.sync.FileContentStreamProvider; import software.amazon.awssdk.http.HttpExecuteRequest; import software.amazon.awssdk.http.HttpExecuteResponse; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.apache.ApacheHttpClient; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest; import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Paths; import java.time.Duration; import java.util.Map; import java.util.UUID;

Generieren Sie die URL.

/** * Creates a presigned URL to use in a subsequent HTTP PUT request. The code adds query parameters * to the request instead of using headers. By using query parameters, you do not need to add the * the parameters as headers when the PUT request is eventually sent. * * @param bucketName Bucket name where the object will be uploaded. * @param keyName Key name of the object that will be uploaded. * @param queryParams Query string parameters to be added to the presigned URL. * @return */ public String createPresignedUrl(String bucketName, String keyName, Map<String, String> queryParams) { try (S3Presigner presigner = S3Presigner.create()) { // Create an override configuration to store the query parameters. AwsRequestOverrideConfiguration.Builder overrideConfigurationBuilder = AwsRequestOverrideConfiguration.builder(); queryParams.forEach(overrideConfigurationBuilder::putRawQueryParameter); PutObjectRequest objectRequest = PutObjectRequest.builder() .bucket(bucketName) .key(keyName) .overrideConfiguration(overrideConfigurationBuilder.build()) // Add the override configuration. .build(); PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) // The URL expires in 10 minutes. .putObjectRequest(objectRequest) .build(); PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest); String myURL = presignedRequest.url().toString(); logger.info("Presigned URL to upload a file to: [{}]", myURL); logger.info("HTTP method: [{}]", presignedRequest.httpRequest().method()); return presignedRequest.url().toExternalForm(); } }

Laden Sie die Datei mit SdkHttpClient hoch.

/** * Use the AWS SDK for Java V2 SdkHttpClient class to execute the PUT request. Since the * URL contains the query parameters, no headers are needed for metadata, SSE settings, or ACL settings. * * @param presignedUrlString The URL for the PUT request. * @param fileToPut File to uplaod */ public void useSdkHttpClientToPut(String presignedUrlString, File fileToPut) { logger.info("Begin [{}] upload", fileToPut.toString()); try { URL presignedUrl = new URL(presignedUrlString); SdkHttpRequest.Builder requestBuilder = SdkHttpRequest.builder() .method(SdkHttpMethod.PUT) .uri(presignedUrl.toURI()); SdkHttpRequest request = requestBuilder.build(); HttpExecuteRequest executeRequest = HttpExecuteRequest.builder() .request(request) .contentStreamProvider(new FileContentStreamProvider(fileToPut.toPath())) .build(); try (SdkHttpClient sdkHttpClient = ApacheHttpClient.create()) { HttpExecuteResponse response = sdkHttpClient.prepareRequest(executeRequest).call(); logger.info("Response code: {}", response.httpResponse().statusCode()); } } catch (URISyntaxException | IOException e) { logger.error(e.getMessage(), e); } }

Sehen Sie sich das vollständige Beispiel an und testen Sie es weiter GitHub.

Prüfen Sie, welche Header eine vorsignierte Anfrage benötigt

Um zu überprüfen, welche Header eine bestimmte vorsignierte Anfrage vom Aufrufer senden muss, rufen Sie signedHeaders () auf der zurückgegebenen Anfrage auf. PresignedRequest Jeder x-amz-* Name in der zurückgegebenen Map ist ein Header, den der Aufrufer senden muss. Wenn Sie einen Header aus der Anforderung entfernen möchten, geben Sie seinen Wert durch, putRawQueryParameter anstatt das eingegebene Feld festzulegen.