Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Travaillez avec Amazon S3 URL pré-signées
Pre-signed Les URL fournissent un accès temporaire à des objets S3 privés sans que les utilisateurs aient besoin AWS d'informations d'identification ou d'autorisations.
Par exemple, supposons qu'Alice ait accès à un objet S3 et qu'elle souhaite partager temporairement l'accès à cet objet avec Bob. Alice peut générer une requête GET pré-signée à partager avec Bob afin qu'il puisse télécharger l'objet sans avoir besoin d'accéder aux informations d'identification d'Alice. Vous pouvez générer des URL pré-signées pour les requêtes HTTP GET et HTTP PUT.
Générez une URL pré-signée pour un objet, puis téléchargez-le (requête GET)
L'exemple suivant comprend deux parties.
-
Partie 1 : Alice génère l'URL pré-signée pour un objet.
-
Partie 2 : Bob télécharge l'objet à l'aide de l'URL pré-signée.
Partie 1 : Générer l'URL
Alice possède déjà un objet dans un compartiment S3. Elle utilise le code suivant pour générer une chaîne d'URL que Bob peut utiliser dans une requête GET ultérieure.
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(); } }
Partie 2 : Téléchargez l'objet
Bob utilise l'une des options de code suivantes pour télécharger l'objet. Il pourrait également utiliser un navigateur pour exécuter la requête GET.
/* 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(); }
AWS SDK for Java 2.x Fournit une extension d'URL pré-signée S3AsyncClient qui télécharge des objets à l'aide d'une URL pré-signée via le pipeline asynchrone du SDK. Accédez à l'extension avecS3AsyncClient.presignedUrlExtension(). Cette fonctionnalité est disponible dans les versions SDK 2.48.0 et ultérieures.
Limitation du client CRT
Le client AWS CRT-based S3 (S3AsyncClient.crtBuilder()) ne prend actuellement pas en charge l'extension d'URL pré-signée. Utilisez S3AsyncClient.builder() à la place.
Configuration requise pour le mode Checksum
Pour valider l'intégrité des données, sélectionnez checksumMode(ChecksumMode.ENABLED) le GetObjectRequest moment où vous générez l'URL pré-signée. Spécifiez le mode de somme de contrôle au moment de la présignature. Vous ne pourrez pas l'ajouter ultérieurement lorsque vous lancerez le téléchargement. Lorsque vous utilisez l'extension d'URL S3AsyncClient pré-signée, le SDK envoie automatiquement l'en-tête requis. x-amz-checksum-mode
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;
Télécharger dans un fichier ou en octets
Téléchargement en plusieurs parties pour les fichiers volumineux
Pour télécharger des objets volumineux en parallèle, définissez multipartEnabled(true) sur le client :
Utiliser le gestionnaire de transfert Amazon S3
Avec Amazon S3 Transfer Manager, vous pouvez télécharger des objets à l'aide d'URL pré-signées avec suivi de la progression. TransferListener
Ajoutez l's3-transfer-managerartefact à votre projet :
<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 Trouvez la dernière version de la nomenclature sur le référentiel central de Maven.
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;
La pause et la reprise ne sont pas prises en charge
Contrairement à la FileDownload norme, PresignedFileDownload ne prend pas en charge la pause et la reprise car les URL pré-signées peuvent expirer pendant un transfert suspendu.
Pour plus d'informations sur Amazon S3 Transfer Manager, y compris les options de configuration et des exemples supplémentaires, consultezTransférez des fichiers et des répertoires avec Amazon S3 Transfer Manager.
Consultez l'exemple complet
Générez une URL pré-signée pour un téléchargement, puis chargez un fichier (requête PUT)
L'exemple suivant comprend deux parties.
-
Partie 1 : Alice génère l'URL pré-signée pour télécharger un objet.
-
Partie 2 : Bob télécharge un fichier à l'aide de l'URL pré-signée.
Partie 1 : Générer l'URL
Alice possède déjà un compartiment S3. Elle utilise le code suivant pour générer une chaîne d'URL que Bob peut utiliser dans une requête PUT ultérieure.
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(); } }
Partie 2 : Charger un objet de fichier
Bob utilise l'une des trois options de code suivantes pour charger un fichier.
/* 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); } }
Consultez l'exemple complet
Inclure les champs de demande en tant que paramètres de requête URL
Certains champs de requête sont situés sur GetObjectRequest requestPayer, acl metadataserverSideEncryption, et storageClass mappez vers x-amz-* les en-têtes. Lorsque vous pré-signez une demande qui définit l'un de ces champs, la signature couvre les en-têtes. Cependant, l'URL pré-signée renvoyée par S3Presigner
L'appelant de l'URL pré-signée doit envoyer les mêmes x-amz-* en-têtes avec la demande. Dans le cas contraire, Amazon S3 est renvoyéSignatureDoesNotMatch. Les clients HTTP qui peuvent définir des en-têtes personnalisés envoient ces en-têtes directement. Par exemple, les SdkHttpClient HttpURLConnectionHttpClient, et présentés précédemment le font tous. Toutefois, si l'appelant ne peut pas définir d'en-têtes personnalisés, la demande échoue. Les exemples courants incluent un navigateur Web ouvrant l'URL sous forme de lien, un formulaire HTML chargé directement sur Amazon S3 et tout client HTTP qui reçoit uniquement l'URL en entrée.
Pour que l'URL fonctionne sans en-têtes supplémentaires, transmettez la valeur en tant que paramètre de requête signé au lieu de définir le champ saisi. À utiliser, RawQueryParameter
Pre-sign une requête GET avec le demandeur-payeur
L'exemple suivant génère une URL pré-signée pour a GetObjectRequest avec le paramètre demandeur-payeur. Comme la valeur est un paramètre de requête, tout appelant peut utiliser l'URL sans envoyer d'x-amz-request-payeren-tête.
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 une requête PUT avec des métadonnées
L'exemple suivant génère une URL pré-signée pour a PutObjectRequest avec deux valeurs de métadonnées en tant que paramètres de requête signés. Les valeurs étant des paramètres de requête, tout appelant peut utiliser l'URL sans envoyer d'x-amz-meta-*en-têtes.
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 une requête PUT et téléchargement d'un fichier
L'exemple suivant illustre le flux de travail complet : une méthode qui pré-signe une requête PUT avec tous les x-amz-* noms et valeurs que vous fournissez sous forme de carte, et une méthode qui télécharge le fichier avec. SdkHttpClient Comme les valeurs font déjà partie de l'URL signée, la méthode de téléchargement ne définit aucun x-amz-* en-tête. En revanche, les exemples de téléchargement précédents définissaient x-amz-meta-* les en-têtes de manière explicite.
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;
Générez l’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(); } }
Téléchargez le fichier avecSdkHttpClient.
/** * 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); } }
Consultez l'exemple complet
Vérifiez quels en-têtes une demande pré-signée nécessite
Pour vérifier quels en-têtes une demande pré-signée spécifique doit être envoyée par l'appelant, appelez SignedHeaders () sur les en-têtes renvoyés. x-amz-* nom figurant dans la carte renvoyée est un en-tête que l'appelant doit envoyer. Si vous souhaitez supprimer un en-tête de l'exigence, transmettez sa valeur au putRawQueryParameter lieu de définir le champ saisi.