Carga de una imagen en un blob de Azure Storage

Use una aplicación de React cliente para cargar un archivo de imagen en un blob de Azure Storage mediante un paquete npm Azure Storage @azure/storage-blob.

El trabajo de programación de TypeScript se realiza automáticamente. Este tutorial se centra en el uso correcto de los entornos de Azure locales y remotos desde Visual Studio Code con extensiones de Azure.

Arquitectura y funcionalidad de la aplicación

En este artículo se incluyen varias tareas principales de Azure para desarrolladores de JavaScript:

  • Ejecución local de una aplicación React/TypeScript con Visual Studio Code
  • Creación de un recurso de Azure Storage Blob y configuración para cargas de archivos
    • Configuración de CORS
    • Creación de token de firmas de acceso compartido (SAS)
  • Configuración del código para que la biblioteca cliente de Azure SDK use el token de SAS para autenticarse en el servicio

La aplicación React de ejemplo, disponible en GitHub, consta de los siguientes elementos:

Aplicación React sencilla conectada a blobs de Azure Storage.

1. Configuración del entorno de desarrollo

2. Bifurcación y clonación de la aplicación de ejemplo

  1. Abra esta dirección URL de GitHub de ejemplo en un explorador web:

    https://github.com/Azure-Samples/js-e2e-browser-file-upload-storage-blob
    
  2. Seleccione Bifurcar para crear su propia bifurcación de este proyecto de ejemplo. Su propia bifurcación de GitHub es necesaria para implementar este ejemplo en Azure como una aplicación web estática.

  3. Seleccione el botón Código y, a continuación, copie la dirección URL de clonación.

  4. En un terminal de Bash, clone el repositorio bifurcado y reemplace REPLACE-WITH-YOUR-ACCOUNT-NAME por el nombre de la cuenta de GitHub:

    git clone https://github.com/REPLACE-WITH-YOUR-ACCOUNT-NAME/js-e2e-browser-file-upload-storage-blob
    
    
  5. Cambie al nuevo directorio y abra Visual Studio Code.

    cd js-e2e-browser-file-upload-storage-blob && code .
    

3. Instalación de dependencias y ejecución de un proyecto local

  1. En Visual Studio Code, abra un terminal de Bash, CtrlMayús`, y ejecute el siguiente comando para instalar las dependencias del ejemplo.

    npm install
    
  2. En la misma ventana de terminal, ejecute el comando para ejecutar la aplicación web.

    npm start
    
  3. Abra un explorador web y use la siguiente dirección URL para ver la aplicación web en el equipo local.

    http://localhost:3000/
    

    Si ve la aplicación web sencilla en el explorador con el texto que indica que Storage no se ha configurado, ha realizado correctamente esta sección del tutorial.

    Aplicación Node.js sencilla conectada a la base de datos de MongoDB.

  4. Detenga el código con CtrlC en Visual Studio Code terminal.

4. Creación de un recurso de almacenamiento con la extensión de Visual Studio

  1. Vaya a la extensión de Azure Storage. Haga clic con el botón derecho en la suscripción y, a continuación, seleccione Create Storage Account... (Crear cuenta de almacenamiento).

    Vaya a la extensión de Azure Storage. Haga clic con el botón derecho en la suscripción y, a continuación, seleccione

  2. Siga las indicaciones que se indican en la tabla siguiente para comprender cómo crear el recurso de Storage.

    Propiedad. Valor
    Escriba un nombre único global para la nueva aplicación web. Escriba un valor, como por ejemplo fileuploaddemo, para el nombre del recurso de almacenamiento.

    Este nombre único es el nombre de recurso que se utiliza en la sección siguiente. Use solo caracteres y números, de hasta 24 caracteres de longitud. Necesitará este nombre de cuenta para utilizarlo más adelante.
  3. Una vez finalizado el proceso de creación de la aplicación, aparece una notificación con información sobre el nuevo recurso.

    Una vez finalizado el proceso de creación de la aplicación, aparece una notificación con información sobre el nuevo recurso.

5. Generación del token de firma de acceso compartido (SAS)

Genere el token de SAS antes de configurar CORS.

  1. En la extensión de Visual Studio Code para Azure Storage, haga clic con el botón derecho en el recurso y seleccione Open in Portal (Abrir en el portal). Se abrirá Azure Portal en ese recurso de almacenamiento exacto.

  2. En la sección Seguridad y redes, seleccione Firma de acceso compartido.

  3. Configure el token de SAS con los valores siguientes.

    Propiedad Valor
    Servicios permitidos Blob
    Tipos de recursos permitidos Servicio, contenedor, objeto
    Permisos permitidos Leer, escribir, eliminar, enumerar, agregar, crear
    Permisos de control de versiones de blobs Activada
    Permitir permisos de índice de blobs Leer, escribir y filtrar deben estar seleccionados.
    Fecha y hora de inicio y caducidad Acepte la fecha y hora de inicio y establezca la fecha y hora de finalización 24 horas en el futuro. El token de SAS solo es válido durante 24 horas.
    HTTPS solamente Seleccionado
    Nivel de enrutamiento preferido Básico
    Clave de firma Clave 1 seleccionada

    Configure el token de SAS como se muestra en la imagen. La configuración se explica debajo de la imagen.

  4. Seleccione Generar la cadena de conexión y SAS.

  5. Copie inmediatamente el token de SAS. No podrá volver a enumerar este token, por lo que, si no lo ha copiado, tendrá que generar un nuevo token de SAS.

6. Establecimiento de los valores de Storage en un archivo .env

El token de SAS se utiliza cuando se realizan consultas al recurso basado en la nube.

  1. Cree un nombre de archivo .env en la raíz del proyecto.

  2. Agregue dos variables necesarias con sus valores de almacenamiento:

    REACT_APP_STORAGESASTOKEN=
    REACT_APP_STORAGERESOURCENAME=
    

    React creará los archivos estáticos con estas variables.

  3. Si el token comienza con un signo de interrogación, elimine el símbolo de interrogación ?. El archivo de código proporciona el símbolo de interrogación ?, por lo que no lo necesita en el token.

7. Configuración de CORS para el recurso de Azure Storage

Configure CORS para el recurso para que el código de React del cliente pueda acceder a la cuenta de almacenamiento.

  1. Mientras sigue en Azure Portal, en la sección Configuración, seleccione Uso compartido de recursos (CORS) .

  2. Configure CORS de Blob service como se muestra en la imagen. La configuración se explica debajo de la imagen.

    Propiedad Valor
    Orígenes permitidos *
    Métodos permitidos Todos excepto revisión.
    Encabezados permitidos *
    Encabezados expuestos *
    Antigüedad máxima 86400

    Configure CORS como se muestra en la imagen. La configuración se explica debajo de la imagen.

  3. Seleccione la opción Guardar situada sobre los valores para guardarlos en el recurso. El código no requiere ningún cambio para trabajar con esta configuración de CORS.

8. Ejecución local del proyecto para comprobar la conexión a la cuenta de almacenamiento

El token de SAS y el nombre de la cuenta de almacenamiento se establecen en el archivo src/azure-storage-blob.ts, por lo que está listo para ejecutar la aplicación.

  1. Si la aplicación no está en ejecución, iníciela de nuevo:

    npm start
    
  2. Abra la siguiente dirección URL en un explorador:

    http://localhost:3000

    El sitio web de React conectado a los blobs de Azure Storage debería mostrar un botón de selección de archivos y un botón de carga de archivos.

  3. Seleccione una imagen de la images carpeta que desea cargar y, a continuación, seleccione el images .

  4. El código del cliente de front-end de React llama a ./src/azure-storage-blob.ts para autenticarse en Azure y, después, crear un contenedor de almacenamiento (si aún no existe) y, a continuación, cargar el archivo en ese contenedor.

9. Implementación de una aplicación web estática en Azure

  1. En Visual Studio Code, seleccione el explorador de Azure.

  2. Si ve una ventana emergente que le pide que confirme los cambios, no lo haga. El ejemplo debe estar listo para implementarse sin cambios.

    Para revertir los cambios, en Visual Studio Code, seleccione el icono Control de código fuente en la barra de actividad. A continuación, seleccione cada archivo modificado en la lista Cambios y seleccione el icono Descartar cambios.

  3. Haga clic con el botón derecho en el nombre de la suscripción y seleccione Create Static Web App (Advanced) [(Crear aplicación web estática (avanzada)].

  4. Siga los mensajes para proporcionar la siguiente información:

    Prompt Entrar
    Escriba el nombre de la nueva aplicación web estática. Cree un nombre único para el recurso. Por ejemplo, puede anteponer su nombre al nombre del repositorio, como en upload-file-to-storage.
    Seleccione un grupo de recursos para los nuevos recursos. Use el grupo de recursos que creó para el recurso de almacenamiento.
    Seleccionar una SKU En este tutorial, seleccione la SKU gratuita. Si ya tiene un recurso de aplicación web estática gratuito utilizado, seleccione el siguiente plan de tarifa.
    Elija el valor preestablecido de compilación para configurar la estructura predeterminada del proyecto. Seleccione React.
    Seleccione la ubicación del código de la aplicación. /: indica que el archivo package.json está en la raíz del repositorio.
    Seleccione la ubicación del código de Azure Functions. Acepte el valor predeterminado. Aunque este ejemplo no usa una API, puede agregar una más adelante.
    Escriba la ruta de la salida de la compilación... build

    Esta es la ruta de acceso desde la aplicación hasta los archivos estáticos (generados).
    Seleccione una ubicación para los nuevos recursos. Seleccione una región cercana.
  5. Una vez completado el proceso, aparecerá un elemento emergente de notificación. Seleccione Ver/Editar flujo de trabajo.

    Captura de pantalla parcial del elemento emergente de notificación de Visual Studio Code con el botón Ver/Editar flujo de trabajo resaltado.

10. Incorporación de secretos de Azure Storage a secretos de GitHub

  1. En un explorador web, vuelva a la bifurcación de GitHub del proyecto de ejemplo para agregar los dos secretos y sus valores:

    https://github.com/YOUR-GITHUB-ACCOUNT/js-e2e-browser-file-upload-storage-blob/settings/secrets/actions
    

    Captura de pantalla de un explorador web que muestra , en  la página Configuración - Secretos, con el botón Nuevo secreto  del repositorio resaltado.

11. Configuración de una aplicación web estática para conectarse al recurso de almacenamiento

Edite el flujo de trabajo de GitHub y los secretos para conectarse a Azure Storage.

  1. En Visual Studio Code, abra el archivo YAML del flujo de trabajo .github/workflows y agregue las dos variables de entorno de almacenamiento después de la sección with en build_and_deploy_job.

    jobs:
      build_and_deploy_job:
        if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
        runs-on: ubuntu-latest
        name: Build and Deploy Job
        steps:
          - uses: actions/checkout@v2
            with:
              submodules: true
          - name: Build And Deploy
            id: builddeploy
            uses: Azure/static-web-apps-deploy@v1
            with:
              azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_123456 }}
              repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
              action: "upload"
              ###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
              # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
              app_location: "/" # App source code path
              api_location: "api" # Api source code path - optional
              output_location: "build" # Built app content directory - optional
              ###### End of Repository/Build Configurations ######
            env: # Add environment variables here
                REACT_APP_STORAGESASTOKEN: ${{secrets.REACT_APP_STORAGESASTOKEN}}
                REACT_APP_STORAGERESOURCENAME: ${{secrets.REACT_APP_STORAGERESOURCENAME}}
    

    Esto permite incorporar los cambios de los secretos en el proceso de creación.

  2. En Visual Studio Code, seleccione Control de código fuente, CtrlMayús G y, a continuación, seleccione el icono de suma para agregar el archivo *.yml cambiado.

  3. Escriba un comentario para la confirmación, como Adding Storage secrets.

  4. Para enviar los cambios a la bifurcación de GitHub, seleccione el icono Sincronizar cambios en la barra de estado.

    Captura de pantalla parcial de la barra de estado de Visual Studio Code.

  5. En la ventana emergente para confirmar si desea enviar e incorporar los cambios del repositorio remoto, seleccione Aceptar.

    Si recibe un error en este paso, compruebe el git remoto para asegurarse de que ha clonado la bifurcación: .

  6. Esta envío de cambios desencadena una nueva creación e implementación de la aplicación web estática.

12. Comprobación de que se completa el trabajo de creación e implementación

  1. En un explorador web, vuelva a la bifurcación de GitHub del proyecto de ejemplo.

  2. Seleccione Acciones y, a continuación, seleccione la acción integración continua y entrega continua de Azure Static Web Apps.

  3. Seleccione el trabajo de creación e implementación para ver cómo se completa el proceso.

    Captura de pantalla del explorador web que muestra una acción de GitHub que finaliza correctamente

13. Uso de la aplicación web estática implementada en Azure

  1. En Visual Studio Code, haga clic con el botón derecho en la aplicación web estática en el explorador de Azure y seleccione

    Captura de pantalla parcial en la que se selecciona Browse Site (Examinar sitio) en el sitio web estático de Azure.

  2. En la nueva ventana del explorador web, elija un archivo y cárguelo.

Solución de problemas de la conexión local a la cuenta de almacenamiento

Si ha recibido un error o el archivo no se carga en el contenedor, compruebe lo siguiente:

  • Vuelva a crear el token de SAS, asegurándose de que el token se crea en el nivel de recurso de almacenamiento y no en el nivel de contenedor. Copie el nuevo token en el código en la ubicación correcta.
  • Compruebe que la cadena del token que copió en el código no contiene el símbolo ? (signo de interrogación) al principio de la cadena.
  • Compruebe la configuración de CORS del recurso de almacenamiento.

Funcionalidad del botón de carga

El archivo de TypeScript src/App.tsx se proporciona como parte de la creación de la aplicación con create-react-app. El archivo se ha modificado para proporcionar el botón de selección de archivos y el botón de carga, así como el código auxiliar para proporcionar esa funcionalidad.

El código que se conecta al código de Azure Blob Storage está resaltado. La llamada a uploadFileToBlob devuelve todos los blobs (archivos) del contenedor como una lista plana. Esa lista se muestra con la función DisplayImagesFromContainer.

// ./src/App.tsx

import React, { useState } from 'react';
import Path from 'path';
import uploadFileToBlob, { isStorageConfigured } from './azure-storage-blob';

const storageConfigured = isStorageConfigured();

const App = (): JSX.Element => {
  // all blobs in container
  const [blobList, setBlobList] = useState<string[]>([]);

  // current file to upload into container
  const [fileSelected, setFileSelected] = useState(null);

  // UI/form management
  const [uploading, setUploading] = useState(false);
  const [inputKey, setInputKey] = useState(Math.random().toString(36));

  const onFileChange = (event: any) => {
    // capture file into state
    setFileSelected(event.target.files[0]);
  };

  const onFileUpload = async () => {
    // prepare UI
    setUploading(true);

    // *** UPLOAD TO AZURE STORAGE ***
    const blobsInContainer: string[] = await uploadFileToBlob(fileSelected);

    // prepare UI for results
    setBlobList(blobsInContainer);

    // reset state/form
    setFileSelected(null);
    setUploading(false);
    setInputKey(Math.random().toString(36));
  };

  // display form
  const DisplayForm = () => (
    <div>
      <input type="file" onChange={onFileChange} key={inputKey || ''} />
      <button type="submit" onClick={onFileUpload}>
        Upload!
          </button>
    </div>
  )

  // display file name and image
  const DisplayImagesFromContainer = () => (
    <div>
      <h2>Container items</h2>
      <ul>
        {blobList.map((item) => {
          return (
            <li key={item}>
              <div>
                {Path.basename(item)}
                <br />
                <img src={item} alt={item} height="200" />
              </div>
            </li>
          );
        })}
      </ul>
    </div>
  );

  return (
    <div>
      <h1>Upload file to Azure Blob Storage</h1>
      {storageConfigured && !uploading && DisplayForm()}
      {storageConfigured && uploading && <div>Uploading</div>}
      <hr />
      {storageConfigured && blobList.length > 0 && DisplayImagesFromContainer()}
      {!storageConfigured && <div>Storage is not configured.</div>}
    </div>
  );
};

export default App;

Carga de archivos en un blob de Azure Storage con la biblioteca cliente del SDK de Azure

El código para cargar el archivo en Azure Storage es independiente del marco. Dado que el código está compilado para un tutorial, se han seleccionado distintas opciones para garantizar su simplicidad y comprensión. Estas opciones están explicadas. Se recomienda que revise su propio proyecto para determinar su finalidad, seguridad y eficiencia.

El ejemplo crea y usa un contenedor y archivos accesibles públicamente. Si desea proteger los archivos en su propio proyecto, dispone de muchos niveles de control, desde requerir la autenticación global en el recurso hasta permisos muy específicos en cada objeto de blob.

Dependencias y variables

El archivo de TypeScript azure-storage-blob.ts carga las dependencias y extrae las variables necesarias mediante variables de entorno o cadenas codificadas de forma rígida.

Variable Descripción
sasToken El token de SAS creado con Azure Portal lleva ? antepuesto. Quite ese prefijo antes de establecerlo en la variable sasToken.
container Nombre del contenedor en el almacenamiento de blobs. Imagine esto como un equivalente a una carpeta o un directorio para un sistema de archivos.
storageAccountName Nombre del recurso.
// THIS IS SAMPLE CODE ONLY - NOT MEANT FOR PRODUCTION USE
import { BlobServiceClient, ContainerClient} from '@azure/storage-blob';

const containerName = `tutorial-container`;
const sasToken = process.env.REACT_APP_STORAGESASTOKEN;
const storageAccountName = process.env.REACT_APP_STORAGERESOURCENAME;

Creación de un cliente de Storage y administración de pasos

La función uploadFileToBlob es la función principal del archivo. Crea el objeto de cliente para el servicio Storage y, a continuación, crea el cliente en el objeto contenedor, carga el archivo y, después, obtiene una lista de todos los blobs del contenedor.

const uploadFileToBlob = async (file: File | null): Promise<string[]> => {
  if (!file) return [];

  // get BlobService = notice `?` is pulled out of sasToken - if created in Azure portal
  const blobService = new BlobServiceClient(
    `https://${storageAccountName}.blob.core.windows.net/?${sasToken}`
  );

  // get Container - full public read access
  const containerClient: ContainerClient = blobService.getContainerClient(containerName);
  await containerClient.createIfNotExists({
    access: 'container',
  });

  // upload file
  await createBlobInContainer(containerClient, file);

  // get list of blobs in container
  return getBlobsInContainer(containerClient);
};

Carga de un archivo en el blob

La función carga el archivo en el contenedor mediante la clase createBlobInContainercreateBlobInContainerel método uploadData. El tipo de contenido se debe enviar con la solicitud si tiene previsto usar la funcionalidad del explorador, que depende del tipo de archivo, como mostrar una imagen.

const createBlobInContainer = async (containerClient: ContainerClient, file: File) => {
  
  // create blobClient for container
  const blobClient = containerClient.getBlockBlobClient(file.name);

  // set mimetype as determined from browser with file upload control
  const options = { blobHTTPHeaders: { blobContentType: file.type } };

  // upload file
  await blobClient.uploadData(file, options);
}

Obtención de la lista de blobs

La función obtiene una lista de direcciones URL mediante la clase getBlobsInContainergetBlobsInContainer el método listBlobsFlat, para los blobs del contenedor. Las direcciones URL se construyen para usarse como src de una visualización de imagen en HTML: <img src={item} alt={item} height="200" />.

// return list of blobs in container to display
const getBlobsInContainer = async (containerClient: ContainerClient) => {
  const returnedBlobUrls: string[] = [];

  // get list of blobs in container
  // eslint-disable-next-line
  for await (const blob of containerClient.listBlobsFlat()) {
    // if image is public, just construct URL
    returnedBlobUrls.push(
      `https://${storageAccountName}.blob.core.windows.net/${containerName}/${blob.name}`
    );
  }

  return returnedBlobUrls;
}

Limpieza de recursos

En Visual Studio Code, use el explorador de Azure para grupos de recursos, haga clic con el botón derecho en el grupo y seleccione Eliminar.

Esto elimina todos los recursos del grupo, incluidos los recursos de almacenamiento y de la aplicación web estática.

Pasos siguientes

Si desea continuar con esta aplicación, obtenga información sobre cómo implementar la aplicación en Azure para su hospedaje con una de las siguientes opciones: