Nube de primavera: AWS S3

AWS S3 permite a los usuarios administrar sus datos estáticos de manera confiable y eficiente. A través del módulo de Spring Cloud, podemos acceder y utilizar fácilmente S3 desde nuestros proyectos de Spring.

Introducción

Servicios web de Amazon (AWS) ofrece una amplia gama de servicios informáticos bajo demanda y fiables. Lo hace ocultando la gestión de la infraestructura y sus complejidades, lo que simplifica el proceso de aprovisionamiento y ejecución de la infraestructura en la nube.

AWS permite que las empresas de TI y los desarrolladores se concentren en crear mejores soluciones para sus productos con servicios web escalables y bajo demanda que facilitan aumentar o disminuir cualquier recurso a medida que la aplicación evoluciona con el tiempo.

Uno de estos productos es el Servicio de almacenamiento simple, o S3, que le permite almacenar archivos a escala de forma económica.

Cubo S3

El Servicio de almacenamiento sencillo de Amazon permite a los usuarios administrar sus datos estáticos de manera confiable y eficiente almacenándolos en los servidores de Amazon. Se puede acceder a los datos almacenados en cualquier momento desde cualquier lugar a través de Internet.

Se puede acceder a los datos almacenados en un depósito S3 a través de Amazon Management Console, que es una interfaz de interfaz de usuario, así como la Interfaz de línea de comandos de AWS y API REST de S3 para desarrolladores.

Nube de primavera AWS

Los servicios de AWS se pueden integrar en las aplicaciones de Java mediante Primavera, que es un marco web de Java muy conocido y el más utilizado. Spring Cloud para los servicios web de Amazon permite a los desarrolladores acceder a los servicios de AWS con una huella de código más pequeña y una integración sencilla.

Cliente Spring Amazon S3

El S3 Bucket en el que se almacenan nuestros datos es accesible a través del cliente Amazon S3 de Spring, que ofrece operaciones generales para administrar datos en el servidor. En esta sección, le mostraremos cómo incluir esta biblioteca de cliente en su proyecto y luego veremos algunas de las operaciones comunes de S3 disponibles a través del cliente.

Dependencias Maven

El primer paso para integrar AWS en un proyecto de Spring es, por supuesto, importar las dependencias requeridas. En este caso, usaremos speing-cloud-starter-aws, que contiene las dependencias spring-cloud-aws-context y spring-cloud-aws-autoconfigure:

1
2
3
4
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-aws</artifactId>
</dependency>

Configuración de Spring Cloud AWS

Dado que estamos usando Spring Boot, naturalmente, la mayor parte de la configuración la realiza el propio marco. Sin embargo, las configuraciones relacionadas con AWS deben especificarse en el archivo application.yaml:

1
2
3
4
5
6
cloud:
  aws:
    region.static: "[S3 Bucket region]"
    credentials:
      accessKey: "xxxxxxx"
      secretKey: "xxxxxxx"

Tenga en cuenta que los nombres y las estructuras de las propiedades tienen un formato estricto y Spring Boot los utilizará para establecer una conexión válida con los servicios de AWS.

El objeto "supervisar" para la gestión de solicitudes al depósito S3, utilizando el cliente S3 de Amazon, es una instancia de la clase AmazonS3:

1
2
@Autowired
private AmazonS3 amazonS3Client;

Lo conectaremos automáticamente como un bean Spring estándar y las propiedades de nuestro archivo .yaml se usarán para sujetarlo y prepararlo para el trabajo.

Subir archivos a S3

Se puede cargar cualquier tipo de archivo en un S3 Bucket, aunque uno de los casos de uso más comunes es el almacenamiento de imágenes. Mantener los archivos/imágenes almacenados en la nube facilita el acceso a ellos y los mantiene seguros en un servicio estable y rápido que puede escalar los recursos necesarios para servir sus archivos.

Carga directa de archivo/archivo de varias partes

Una vez que el cliente S3 de Amazon sea funcional, puede cargar un nuevo archivo simplemente llamando al método putObject():

1
amazonS3Client.putObject(new PutObjectRequest("bucketName", "fileKey", file));

Donde bucketName es el nombre del depósito S3 al que desea cargar el archivo. fileKey es un valor de cadena que identificará de forma única el archivo que se carga y file es un objeto File válido.

Si tiene un archivo de varias partes que ingresa a su aplicación o microservicio a través de un punto final REST expuesto, también se puede cargar. Esto requiere poco código adicional y simplemente convertimos MultipartFile a File:

1
2
3
4
5
6
7
File file = new File("FileName");
try {
    FileOutputStream fileOutputStream = new FileOutputStream(file)
    fileOutputStream.write(multipartFile.getBytes());
} catch (IOException e) {
    /* Handle Exception */
}

Lo que hemos hecho es simplemente convertir una parte múltiple en un objeto File de Java normal usando un FileOutputStream. Una vez convertido, se puede cargar en el depósito S3 usando el mismo método putObject() anterior.

Subir archivos como metadatos

Al manejar las solicitudes y los datos recibidos a través de los puntos finales de la API, mantener una copia de los datos en nuestro propio servidor antes de cargarlos en nuestro depósito S3 no es rentable y solo aumenta el tamaño de nuestra aplicación innecesariamente, ya que es el recurso principal para el almacenamiento de archivos. será el S3 Bucket.

Para evitar la necesidad de conservar una copia, podemos usar PutObjectRequest de la API de Amazon para cargar el archivo en el depósito enviándolo a través de InputStream y proporcionando detalles del archivo en forma de metadatos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
ObjectMetadata objectMetaData = new ObjectMetadata();
objectMetaData.setContentType(multipartFile.getContentType());
objectMetaData.setContentLength(multipartFile.getSize());

try {
    PutObjectRequest putObjectRequest = new PutObjectRequest("bucketName", "fileName", multipartFile.getInputStream(), objectMetaData);
    amazonS3Client.putObject(putObjectRequest);
} catch (IOException e) {
    /* Handle Exception */
}

El tamaño y el tipo de contenido del archivo se especifican a través del objeto ObjectMetaData. El flujo de entrada del archivo se agrega a PutObjectRequest junto con el nombre del depósito S3 al que estamos cargando, así como el nombre del archivo con el que se asociará.

Una vez que se crea el objeto PutObjectRequest, se puede enviar al S3 Bucket usando el método putObject(), como antes.

Subir archivos con vista pública

En ocasiones, es posible que deseemos que los archivos cargados estén disponibles públicamente. Un lector no debería necesitar autorización para ver las imágenes en una publicación de blog, por ejemplo. Hasta ahora, hemos subido archivos que requieren nuestra autorización para verlos.

AWS' S3 nos brinda opciones para establecer el nivel de acceso en cada archivo cargado, durante su carga.

Para cambiar el nivel de acceso y otorgar acceso público, modifiquemos ligeramente la solicitud de carga de datos:

1
2
new PutObjectRequest("bucketName", "fileName", multipartFile.getInputStream(), objectMetaData)
    .withCannedAcl(CannedAccessControlList.PublicRead)

Agregar la propiedad CannedAccessControlList.PublicRead a PutObjectRequest brinda acceso público de solo lectura para el archivo que se está cargando, lo que permite que cualquier persona con la URL correcta pueda acceder/ver el archivo.

Una vez que se crea el objeto PutObjectRequest, se puede cargar en un depósito S3 usando el mismo método putObject() que antes.

Descarga de archivos desde S3

Una vez cargados, puede descargar fácilmente archivos de su cubo utilizando el método getObject() a través de la instancia de la clase AmazonS3.

El objeto devuelto se empaqueta en una instancia S3Object, que luego se puede transmitir a un Object regular:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
S3Object s3Object = amazonS3Client.getObject("bucketName", "fileName");
S3ObjectInputStream inputStream = s3Object.getObjectContent();
byte[] bytes = StreamUtils.copyToByteArray(inputStream);
File file = new File("File_Name");
try {
    FileOutputStream fileOutputStream = new FileOutputStream(file)
    fileOutputStream.write(bytes);
} catch (IOException e) {
    /* Handle Exception */
}

Si la solicitud para descargar el archivo se realiza a través de un punto final REST, podemos devolver los datos del archivo a la entidad que llama sin crear un “Archivo” mediante el uso de “ResponseEntity” de Spring:

1
2
3
4
5
S3Object s3Object = amazonS3Client.getObject("bucketName", "fileName");
S3ObjectInputStream inputStream = s3Object.getObjectContent();
byte[] bytes = StreamUtils.copyToByteArray(inputStream);
String contentType = s3Object.getObjectMetadata().getContentType();
return ResponseEntity.ok().contentType(contentType).body(bytes);

De esta manera, no tenemos que crear un archivo en nuestro servidor cuando lo descargamos desde el depósito S3, el archivo simplemente se devuelve a la persona que llama en la respuesta de la API.

Eliminar archivo del depósito S3

Eliminar archivos de un depósito S3 es la tarea más sencilla y todo lo que necesita saber es la ruta absoluta al archivo.

Llamar al método deleteObject() con el nombre del depósito y el nombre completo del archivo elimina el archivo del servidor, si existe:

1
amazonS3Client.deleteObject("bucketName", "fileName");

Conclusión

El S3 de Amazon proporciona una manera conveniente de almacenar datos de archivos en la nube y brinda un medio confiable para acceder a los datos cuando sea necesario.

Con Spring Cloud AWS, los desarrolladores pueden acceder fácilmente a los servicios S3 de Amazon desde su aplicación para realizar las operaciones necesarias.

Para las aplicaciones Spring Boot, toda la administración de la conexión con el servidor de Amazon está a cargo de Spring, lo que hace que las cosas sean más simples que usar aws-java-sdk normal con aplicaciones Java simples.

Como se desprende de los fragmentos de código anteriores, acceder al depósito S3 con Spring Cloud AWS es bastante simple y la huella del código también es muy pequeña.

El código fuente del proyecto está disponible en GitHub. cket).