Importar archivos desde Amazon S3 en Java
Integrar Amazon S3 con aplicaciones Java es un requisito común para los desarrolladores que trabajan con almacenamiento en la nube. AWS SDK v2 ofrece una forma robusta y eficiente de gestionar la importación de archivos. En este DevTip, veremos cómo preparar AWS SDK v2, configurar las credenciales de forma segura, importar archivos desde S3, manejar excepciones y optimizar el rendimiento.
Introducción a Amazon S3 y Java
Amazon S3 (Simple Storage Service) es una solución escalable de almacenamiento en la nube para guardar y recuperar datos. Los desarrolladores de Java suelen interactuar con S3 para importar archivos. AWS SDK v2 ofrece una API optimizada para estas operaciones.
Preparar AWS SDK v2
Agrega las dependencias de AWS SDK v2 a tu proyecto. Para Maven, agrégalas a pom.xml:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.30.38</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3-transfer-manager</artifactId>
<version>2.30.38</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk.crt</groupId>
<artifactId>aws-crt</artifactId>
<version>0.34.1</version>
</dependency>
Para Gradle, agrégalas a build.gradle:
implementation 'software.amazon.awssdk:s3:2.30.38'
implementation 'software.amazon.awssdk:s3-transfer-manager:2.30.38'
implementation 'software.amazon.awssdk.crt:aws-crt:0.34.1'
Las dependencias transfer-manager y CRT son necesarias para los ejemplos posteriores. Las versiones anteriores coinciden con la dependencia CRT de AWS SDK 2.30.38. Los fragmentos de Java sin declaración de clase son extractos del cuerpo de un método; coloca sus importaciones al inicio de tu archivo Java.
Configurar las credenciales de AWS
AWS SDK v2 admite varias formas de configurar las credenciales. El enfoque recomendado es usar variables de entorno o archivos de credenciales de AWS.
Con variables de entorno:
export AWS_ACCESS_KEY_ID=your_access_key
export AWS_SECRET_ACCESS_KEY=your_secret_key
O bien, guarda las credenciales en ~/.aws/credentials:
[default]
aws_access_key_id = your_access_key
aws_secret_access_key = your_secret_key
Configurar la región de AWS
Especificar la región de AWS correcta es fundamental. Así es como se configura:
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
// Configure the S3 client with a specific region
Region region = Region.US_EAST_1; // Choose your region
try (S3Client s3 = S3Client.builder()
.region(region)
.build()) {
// Perform S3 operations here while the client is open.
}
Importar archivos desde S3
Este es un ejemplo de cómo importar un archivo desde Amazon S3:
import software.amazon.awssdk.core.sync.ResponseTransformer;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
import java.nio.file.Paths;
public class S3FileImporter {
public static void main(String[] args) {
String bucketName = "your-bucket-name";
String key = "path/to/your/file.txt";
String downloadPath = "downloaded-file.txt";
Region region = Region.US_EAST_1; // Choose your region
try (S3Client s3 = S3Client.builder()
.region(region)
.build()) {
GetObjectRequest request = GetObjectRequest.builder()
.bucket(bucketName)
.key(key)
.build();
s3.getObject(request, ResponseTransformer.toFile(Paths.get(downloadPath)));
System.out.println("File downloaded successfully to " + downloadPath);
} catch (S3Exception e) {
System.err.println("S3 error: " + e.getMessage());
} catch (Exception e) {
System.err.println("Unexpected error: " + e.getMessage());
}
}
}
Manejar excepciones
Dentro del bloque try con el cliente abierto que aparece arriba, reemplaza la llamada a getObject por este manejador. Reutiliza
s3, request, downloadPath y las importaciones de ese ejemplo:
try {
s3.getObject(request, ResponseTransformer.toFile(Paths.get(downloadPath)));
System.out.println("File downloaded successfully.");
} catch (software.amazon.awssdk.services.s3.model.NoSuchKeyException e) {
System.err.println("File not found: " + e.getMessage());
} catch (software.amazon.awssdk.services.s3.model.NoSuchBucketException e) {
System.err.println("Bucket not found: " + e.getMessage());
} catch (software.amazon.awssdk.services.s3.model.S3Exception e) {
System.err.println("S3 error: " + e.getMessage());
} catch (Exception e) {
System.err.println("Unexpected error: " + e.getMessage());
}
Tipos de cliente de S3
AWS SDK for Java v2 ofrece distintos tipos de cliente:
Cliente síncrono (S3Client)
El cliente estándar para la mayoría de las aplicaciones. Las operaciones se bloquean hasta completarse.
Cliente asíncrono (S3AsyncClient)
Ideal para operaciones sin bloqueo; devuelve objetos CompletableFuture:
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.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import java.nio.file.Paths;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
try (S3AsyncClient asyncClient = S3AsyncClient.builder().region(Region.US_EAST_1).build()) {
GetObjectRequest request = GetObjectRequest.builder()
.bucket("your-bucket-name").key("path/to/your/file.txt").build();
CompletableFuture<GetObjectResponse> futureResponse = asyncClient.getObject(
request, AsyncResponseTransformer.toFile(Paths.get("downloaded-file.txt")));
// Other work can run here. Await completion before closing the client or exiting.
futureResponse.join();
System.out.println("File downloaded successfully.");
} catch (CompletionException e) {
System.err.println("Asynchronous download failed: " + e.getCause().getClass().getSimpleName());
}
Cliente de rendimiento mejorado (AWS CRT)
Para alto rendimiento, mediante el AWS Common Runtime (CRT):
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.GetObjectRequest;
import java.nio.file.Paths;
try (S3AsyncClient crtClient = S3AsyncClient.crtBuilder()
.region(Region.US_EAST_1).build()) {
GetObjectRequest request = GetObjectRequest.builder()
.bucket("your-bucket-name").key("path/to/your/file.txt").build();
crtClient.getObject(request, AsyncResponseTransformer.toFile(Paths.get("crt-download.txt")))
.join();
}
Optimizar el rendimiento
Para archivos grandes, considera estas técnicas:
Transmisión a disco
Mientras el cliente síncrono sigue abierto, transmite un objeto a un nuevo destino local:
s3.getObject(request, ResponseTransformer.toFile(Paths.get("large-file.txt")));
Esto transmite el archivo a disco y minimiza el uso de memoria.
Descargas multiparte
Para archivos de más de unos cientos de MB, usa descargas multiparte:
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.DownloadFileRequest;
import java.nio.file.Paths;
try (S3AsyncClient s3AsyncClient = S3AsyncClient.crtBuilder().region(Region.US_EAST_1).build();
S3TransferManager transferManager = S3TransferManager.builder()
.s3Client(s3AsyncClient).build()) {
GetObjectRequest request = GetObjectRequest.builder()
.bucket("your-bucket-name").key("path/to/your/video.mp4").build();
DownloadFileRequest downloadFileRequest = DownloadFileRequest.builder()
.getObjectRequest(request)
.destination(Paths.get("very-large-file.mp4"))
.build();
transferManager.downloadFile(downloadFileRequest).completionFuture().join();
}
Permisos de IAM
Asegúrate de que tu usuario o rol de IAM tenga los permisos mínimos necesarios:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": ["arn:aws:s3:::your-bucket-name/*", "arn:aws:s3:::your-bucket-name"]
}
]
}
Buenas prácticas
- Protege tus credenciales de AWS.
- Usa roles de IAM con permisos mínimos.
- Transmite los archivos grandes a disco.
- Implementa un manejo de errores robusto.
- Elige el tipo de cliente de S3 adecuado.
- Usa el S3TransferManager para archivos grandes.
- Establece tiempos de espera adecuados.
Transloadit ofrece una solución gestionada para importar archivos, incluso desde S3. Consulta nuestro S3 Import Robot y nuestro Java SDK.
