Compartir a través de


Usar API web para cargar archivos en Azure Blob Storage

En esta guía se muestra cómo implementar la API de archivos de Azure. Estos pasos permiten a los usuarios o visitantes de su sitio web ver, editar, crear y eliminar datos adjuntos almacenados en Azure.

Nota

  • Se admite un tamaño de archivo de Azure de hasta 10 GB.
  • Puede cambiar los nombres de las columnas o utilizar una tabla diferente mientras sigue los pasos de este ejemplo.
  • Estas API solo funcionan para registros que ya están creados. Los archivos adjuntos cargados con estas API se vincularán a ese registro.
  • Estas API realizarán varias actualizaciones en la entidad de nota (anotación) a medida que los archivos se carguen en fragmentos.

Requisitos previos

Este tutorial depende de una tabla personalizada denominada File Test. Puede crear una tabla personalizada con el mismo nombre o elegir usar otra tabla. Obtenga más información sobre cómo crear una tabla personalizada en Crear y editar tablas con Power Apps

Paso 1: Crear configuraciones de sitio

Antes de poder utilizar la API de portales de Azure File, debe habilitar la configuración del sitio requerida con la aplicación Administración del portal. La configuración del sitio depende de la tabla que desee utilizar al interactuar con la API Azure File.

  1. Abra la aplicación Administración del portal.

  2. En el panel izquierdo de la aplicación Administración del portal, seleccione Configuración del sitio.

  3. Seleccione Nuevo.

  4. En Nombre, escriba Site/FileManagement/EnableWebAPI.

  5. En la lista Sitio web, seleccione el registro de su sitio web.

  6. En el Valor, introduzca Verdadero.

  7. Seleccione Guardar y cerrar.

  8. Agregue la siguiente configuración del sitio:

    Nombre de configuración del sitio DefaultValue Description Obligatorio
    Site/FileManagement/EnableWebAPI Habilita la API web de administración de archivos
    Site/FileManagement/BlobStorageAccountName Nombre de la cuenta de almacenamiento
    Site/FileManagement/BlobStorageContainerName Nombre de contenedor
    Site/FileManagement/SupportedFileType Valores separados por comas de los tipos de archivo. Por ejemplo: .jpeg, .jpg
    Site/FileManagement/SupportedMimeType ; separados tipos MIME
    Site/FileManagement/MaxFileSize 1 048 576 (1 GB) Tamaño máximo de archivo en KB No
    Site/FileManagement/DownloadViaSASUri Verdadero (habilitada de forma predeterminada) Para decidir si se va a usar el URI de SAS para descargar el archivo No
    Site/FileManagement/DownloadSASUriExpiryTimeSpan 00:10:00 (10 minutos) Intervalo de tiempo de expiración máximo para SAS URI (necesario si 7 es verdadero) No
    Site/FileManagement/DownloadChunkSizeInKB 4096 (4 MB) Para decidir el tamaño del fragmento que se descargará (necesario si 7 es falso) No
  9. Agregue esta configuración adicional del sitio para habilitar la API web para anotaciones (notas):

    Nombre de configuración del sitio valor
    Webapi/annotation/enabled true
    Webapi/annotation/fields *

Paso 2: Configurar permisos

Tendrá que configurar permisos para que los usuarios puedan usar la función de API Azure File. En este ejemplo, debe configurar o crear un nuevo rol web que use la API. A continuación, agregue los permisos de la tabla para las tablas Archivo, Prueba y Nota, y asocie los permisos de la tabla al rol web. Por último, asigna el rol web a los usuarios para permitirles utilizar la API.

Nota

La API sigue los permisos de la tabla del contexto del rol web del usuario autenticado o del rol web anónimo. Piense en si sus usuarios ya tienen un rol web que tiene acceso a las tablas específicas de su sitio web que necesita la API. No es necesario crear roles web adicionales solo para usar la API.

Crear un rol web

Si no tiene un rol web con permisos para la tabla requerida, siga estos pasos para crear un rol web y asignar permisos de tabla.

  1. Abra la aplicación Administración del portal.

  2. En el panel izquierdo, dentro de la sección Seguridad, seleccione Roles web.

  3. Seleccione Nuevo.

  4. Para el Nombre, escriba Usuario de la API de archivos de Azure o cualquier nombre que refleje mejor el rol del usuario que accede a esta funcionalidad.

  5. En la lista Sitio web, seleccione el registro de su sitio web.

  6. Seleccione Guardar.

Crear permisos de tabla

  1. Abra el Estudio de diseño de Power Pages.

  2. Seleccione el espacio de trabajo Seguridad.

  3. En la sección Proteger, seleccione Permisos de tabla.

  4. Seleccione Nuevo permiso.

  5. Para el Nombre, introduzca Permiso de tabla File Test.

  6. En la lista Nombre de tabla, seleccione File Test (cr463_filetest).

  7. En la lista Tipo de acceso, seleccione Acceso global.

  8. Seleccione los privilegios Leery Anexar.

  9. Seleccione + Agregar roles y seleccione el rol web que creó anteriormente.

  10. Seleccione Guardar.

  11. Siga pasos similares para crear un permiso más para la tabla Nota (anotación) con privilegios de Escritura, Lectura, Creación, Anexión y agregar el mismo rol web.

Agregar contactos al rol web

  1. Abra la aplicación Administración del portal.

  2. En el panel izquierdo, dentro de la sección Seguridad, seleccione Contactos.

  3. Seleccione un contacto que quiera usar en este ejemplo para la API.

Nota

Este contacto es la cuenta de usuario utilizada en este ejemplo para probar la API. Asegúrese de seleccionar el contacto correcto en su portal.

  1. Seleccione Relacionado>Roles web. Compruebe que está usando el formulario de contacto del portal. Si utiliza la aplicación Power Pages Management, la subcuadrícula Roles web se encuentra en la parte inferior de la pestaña General.

  2. Seleccione Agregar rol web existente.

  3. Seleccione el rol Usuario API Azure File que creó anteriormente.

  4. Seleccione Agregar.

  5. Seleccione Guardar y cerrar.

Agregar permisos basados en roles para la aplicación Microsoft Entra

  1. Inicie sesión en Azure donde se creó la cuenta de almacenamiento.

  2. Vaya al grupo de recursos que contiene la cuenta de almacenamiento.

  3. Seleccione Control de acceso (IAM)>Agregar>Agregar asignación de roles.

  4. Seleccione el rol Lector y después Siguiente.

  5. Seleccione Usuario, grupo o entidad de servicio y, a continuación, seleccione + Seleccionar miembros.

  6. En el panel lateral derecho, elija la aplicación Portal Enterprise buscando el nombre del sitio y luego seleccione Seleccionar. El nombre de la aplicación en el formato siguiente:

    Portals-<site name>

  7. Seleccione Revisar + asignar>Revisar + asignar.

  8. Vaya a la cuenta de almacenamiento y seleccione Control de acceso (IAM)>Agregar>Agregar asignación de rol.

  9. Seleccione el rol Datos de blob de almacenamiento Colaborador y seleccione Siguiente.

  10. Seleccione Usuario, grupo o entidad de servicio y, a continuación, seleccione + Seleccionar miembros.

  11. En el lado derecho, seleccione la aplicación Portal Enterprise buscando el nombre del sitio y luego seleccione Seleccionar.

  12. Seleccione Revisar + asignar>Revisar + asignar.

Paso 3: Crear un página web

Ahora que ha habilitado la API Azure File y configurado los permisos de usuario, cree una página web con una lista de entidades para la tabla File Test.

  1. Abra el Estudio de diseño de Power Pages.

  2. En el espacio de trabajo Páginas, seleccione + Página y seleccione Otras formas de agregar una página.

  3. En el diálogo Agregar una página, para Nombre de página, introduzca Página File Test y después Empezar desde cero.

  4. Seleccione Agregar.

  5. Seleccione Lista y, a continuación, agregue una nueva lista o elija una lista existente para la tabla File Test.

    Cree una página para archivos adjuntos con el siguiente código de ejemplo para ver, editar, crear y eliminar registros.

  6. Abra el Estudio de diseño de Power Pages.

  7. En el espacio de trabajo Páginas, seleccione + Página y seleccione Otras formas de agregar una página.

  8. En el diálogo Agregar una página, para Nombre de página, introduzca Adjuntos y después Empezar desde cero.

  9. Seleccione Agregar.

  10. Seleccione la opción Editar código en la esquina superior derecha.

  11. Seleccione Abrir Visual Studio Code.

  12. Copie el siguiente fragmento de código de muestra y péguelo entre las etiquetas <div></div> de la sección de la página.

    <style>
    .containerforfile
    {
        display:flex;
        margin-bottom:30px; 
    }
    .btn-for-file
    {
        margin-right:10px;
    }
    .file-name
    {
        padding-top:6px;
    }
    .fileinput
    {
        margin-right:10px;
    }
    .container-progress
    {   
         width: 70%;
         max-width: 400px;  
         margin-top: 10px;   
         position: relative;
    } 
    .parent-progress
    {    
        width: 100%;    
        background-color: #2f5fef;    
        height: 30px;    
        margin-top: 25px;    
        margin-bottom: 20px;
    } 
    .child-progress
    {    
        width: 0%;    
        background-color: #53b453;    
        height: 100%;
    } 
    .prog 
    {    position: absolute;  
      display: block;   
       right: 0; 
    }
    
    #attachments{
        font-family: Arial, Helvetica, sans-serif;
        border-collapse: collapse;
        width: 100%;
      }
      #attachments td,
      #attachments th {
        border: 1px solid #ddd;
        padding: 8px;
      }
      #attachments tr:nth-child(even) {
        background-color: #f2f2f2;
      }
      #attachments tr:hover {
        background-color: #ddd;
      }
      #attachments th {
        padding-top: 12px;
        padding-bottom: 12px;
        text-align: left;
        background-color: #2f5fef;
        color: white;
      }
    </style>
    
    <script>
    function selectFile()
    {var child = document.getElementsByClassName("child-progress")[0];
                                    var progSpan = document.getElementsByClassName("prog")[0];
                                        child.style.width = 0 + "%";
                                    progSpan.innerHTML = 0 + "%";
        var elementToChooseFile = document.getElementById("fileinput");
        elementToChooseFile.click();
    }
    function chooseFile()
    {
        var elementToChooseFile = document.getElementById("fileinput");
        var filename =elementToChooseFile.files[0].name;
        var elementforfilename = document.getElementById("filename");
        elementforfilename.innerText = filename;
        uploadFileinChunks();
    }
    
    (function(webapi, $){
                    function safeAjax(ajaxOptions) {
                        var deferredAjax = $.Deferred();
    
                        shell.getTokenDeferred().done(function (token) {
                        // add headers for AJAX
                        if (!ajaxOptions.headers) {
                        $.extend(ajaxOptions, {
                            headers: {
                                "__RequestVerificationToken": token
                            }
                        }); 
                        } else {
                        ajaxOptions.headers["__RequestVerificationToken"] = token;
                    }
                    $.ajax(ajaxOptions)
                        .done(function(data, textStatus, jqXHR) {
                            validateLoginSession(data, textStatus, jqXHR, deferredAjax.resolve);
                        }).fail(deferredAjax.reject); //AJAX
                }).fail(function () {
                    deferredAjax.rejectWith(this, arguments); // on token failure pass the token AJAX and args
                });
    
                return deferredAjax.promise();  
            }
            webapi.safeAjax = safeAjax;
        })(window.webapi = window.webapi || {}, jQuery)
    
    function getFileName(fileName)
    {
        return fileName.replace(/\.azure\.txt$/, '');
    }
    function downloadFile()
    {
        var entityName = document.getElementById("entity_name").value;
        var entityId = document.getElementById("entity_id").value;
        var url = "/_api/file/download/" + entityName + "(" + entityId + ")/blob/$value";
        window.open(url, "_blank");
    }
    
    function uploadFileinChunks()
    {
        var filesizeelement = document.getElementById("filesize");
        var starttimelement = document.getElementById("starttime");
        starttimelement.innerText = new Date().toLocaleString();
        var endtimeelement = document.getElementById("endtime");
        var entityName = "cr463_filetest";
        var entityId = window.location.search.substring(4);
        var url = "/_api/file/InitializeUpload/" + entityName + "(" + entityId + ")/blob"
        var elementToChooseFile = document.getElementById("fileinput");
        var filename = "";
        if (elementToChooseFile.files.length > 0) {
            filename = elementToChooseFile.files[0].name;
        filesizeelement.innerText = elementToChooseFile.files[0].size / 1048576;
            const encodedFileName = encodeURIComponent(filename);
            filename = encodedFileName;
        }
        if (elementToChooseFile.files.length > 0 && elementToChooseFile.files[0].size > 0)
        {
                const chunkSize = 50*1024 *1024;
                let numberOfBlocks;
                let token;
                if (elementToChooseFile.files[0].size % chunkSize == 0)
                {
                    numberOfBlocks = elementToChooseFile.files[0].size / chunkSize;
                }
                else
                {
                    numberOfBlocks = parseInt(elementToChooseFile.files[0].size / chunkSize, 10) + 1;
                }
                webapi.safeAjax({
                    type: "POST",
                    url: url,//replace this with url 
                    headers: { "x-ms-file-name": elementToChooseFile.files[0].name, "x-ms-file-size": elementToChooseFile.files[0].size },
                    contentType: "application/octet-stream",
                    processData: false,
                    data: {},
                    success: function (response, status, xhr)
                    {
                        token = response;
                        uploadFileChunk(0);
                    },
                    error: function (XMLHttpRequest, textStatus, errorThrown)
                    {
                        alert(XMLHttpRequest.responseText);
                    }
                });
    
                function uploadFileChunk(blockno)
                {
                    var fileReader = new FileReader();
    
                    if (blockno < numberOfBlocks)
                    {
                        var end = (blockno * chunkSize + chunkSize) > elementToChooseFile.files[0].size ? blockno * chunkSize + elementToChooseFile.files[0].size % chunkSize : blockno * chunkSize + chunkSize;
                        var content = elementToChooseFile.files[0].slice(blockno * chunkSize, end);
                        fileReader.readAsArrayBuffer(content);
                    }
                    fileReader.onload = function ()
                    {
                        webapi.safeAjax({
                            type: "PUT",
                            url: "/_api/file/UploadBlock/blob?offset=" + (blockno * chunkSize) + "&fileSize=" + elementToChooseFile.files[0].size + "&chunkSize=" + chunkSize + "&token=" + token,
                            headers: { "x-ms-file-name": elementToChooseFile.files[0].name },
                            contentType: "application/octet-stream",
                            processData: false,
                            data: content,
                            success: function (res) {
                                var child = document.getElementsByClassName("child-progress")[0];
                                    var progSpan = document.getElementsByClassName("prog")[0];
                                    var percentComplete = ((parseFloat(end) / parseFloat(elementToChooseFile.files[0].size)) * 100).toFixed(2);
    
                                    child.style.width = percentComplete + "%";
                                    progSpan.innerHTML = percentComplete + "%";
                                    if (percentComplete == 100) {
                                        var table = document.getElementById('attachments');
                                        if(table.hidden)
                                        {
                                        var divForNoAttachment = document.getElementById("no-attachment-found");
                                        divForNoAttachment.hidden = true;
                                        table.hidden = false;
                                        }
                                        var row = document.createElement("tr"); 
                                        row.id = token;
                                        row.innerHTML=`<td><a target="_blank" href="/_api/file/download/annotation(` + token + `)/blob/$value" >` + elementToChooseFile.files[0].name + `</a></td>
                                                <td>`+  new Date().toLocaleString() + `</td>     
                                                <td><button class="btn btn-default" onClick="deleteFile('` + token + `');"><i class="glyphicon glyphicon-trash" aria-hidden="true"></i></button></td>`;
                                        table.firstElementChild.nextElementSibling.appendChild(row);
                                        endtimeelement.innerText = new Date().toLocaleString();
                                    }
                                uploadFileChunk(blockno + 1);
                            },
                            error: function (XMLHttpRequest, textStatus, errorThrown) {
                                alert(XMLHttpRequest.responseText);
                            }
                        });
                    }
                }
        }
        else
        {
        alert("no file chosen");
        }
    }
    
    function loadAllAttachments()
    {
        var fetchXmlQuery = `<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
      <entity name="annotation">
        <attribute name="filename" />
        <attribute name="annotationid" />  
        <attribute name="createdon"/>
        <attribute name="objectid" />
        <attribute name="objecttypecode" />
        <filter type="and">
        <condition attribute="filename" operator="like" value="%.azure.txt" />
        </filter>
        <link-entity name="cr463_filetest" from="cr463_filetestid" to="objectid" link-type="inner" alias="ad">
        <filter type="and">
        <condition attribute="cr463_filetestid" operator="eq" value="{` + window.location.search.substring(4) +`}"/>
    </filter>
    </link-entity>
      </entity>
    </fetch>`;
    
    var req = new XMLHttpRequest();
    
    req.open("GET", "/_api/annotations?fetchXml=" +  
        encodeURIComponent(fetchXmlQuery), true);
    
    req.setRequestHeader("Accept", "application/json");
    
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    
    req.onreadystatechange = function ()
    {
        if (this.readyState === 4)
        {
            this.onreadystatechange = null;
            if (this.status === 200)
            {
                var returned = JSON.parse(this.responseText);
                var results = returned.value;
                var loading = document.getElementById('loading');
                if (results.length == 0)
                {
                    var divForNoAttachment = document.getElementById("no-attachment-found");
                        divForNoAttachment.hidden = false;
                }
                else
                {
                for (var i = 0; i < results.length; i++)
                {
                    var table = document.getElementById('attachments');
                    if(table.hidden)
                    {
                        var divForNoAttachment = document.getElementById("no-attachment-found");
                        divForNoAttachment.hidden = true;
                        table.hidden = false;
                    }
                    var row = document.createElement("tr"); 
    
                    var fileName = results[i]["filename"];
                    fileName = fileName.replace(".azure.txt", "");
                    var createdOn = results[i]["createdon"];
                    var annotationid = results[i]["annotationid"];
                    row.id = annotationid;
                    row.innerHTML=`<td><a target="_blank" href="/_api/file/download/annotation(` + annotationid + `)/blob/$value" >` + fileName + `</a></td>
                    <td>`+  createdOn + `</td>     
                    <td><button class="btn btn-default" onClick="deleteFile('` + annotationid + `');"><i class="glyphicon glyphicon-trash" aria-hidden="true"></i></button></td>`;
                    table.firstElementChild.nextElementSibling.appendChild(row);
                }
                }
                loading.hidden= true;
            }
            else
            {
                alert(this.status);
            }
        }
    };
    req.send();
    }
    
    document.addEventListener("DOMContentLoaded", function(){
        loadAllAttachments();
    });
    function deleteFile(entityId)
    {
        var entityName = "annotation";
        var url = "/_api/file/delete/" + entityName + "(" + entityId + ")/blob/$value";
        webapi.safeAjax({
            url: url,
            type: "DELETE",
            success: function(){
    
                var row = document.getElementById(entityId);     
                row.parentNode.removeChild(row);
                var table = document.getElementById('attachments');
    
                if(table.hidden == false && table.tBodies[0].children.length == 0)
                { 
                var divForNoAttachment = document.getElementById("no-attachment-found");
                    divForNoAttachment.hidden = false;
                    table.hidden = true;
                }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown)
            {
                alert(XMLHttpRequest.responseText); 
            }
        });
    }
    </script> 
    <div style="margin-left:40px;"> 
    <div class="containerforfile" style="display: flex;"> 
      <input type="file" multiple="true" id="fileinput" onchange="chooseFile()" style="display: none;"> 
      <button type="button" id="button-to-choosefile" onclick="selectFile()" class="btn btn-default btn-for-file">Choose File</button> 
      <div id="filename" class="file-name">No File Selected</div> 
    </div> 
    <br> 
    <div> 
    <label for="filesize" id="file_size_label" class="field-label">FileSize(In MB): </label><div class="filesize" id="filesize"></div> 
    <label for="starttime" id="start_time_label" class="field-label">StartTime:</label><div class="starttime" id="starttime"></div> 
    <label for="endtime" id="end_time_label" class="field-label">EndTime:</label><div class="endtime" id="endtime"></div> 
    </div> 
     <div class="container-progress"> 
         <div class="parent-progress" style="width: 100%;background-color: #c1c1c1;    height: 30px;     margin-top: 25px;    margin-bottom: 20px;">         
            <div class="child-progress" style="width: 0%;    background-color: #53b453;    height: 100%;"></div>    
          </div>            
         <span class="prog">0%</span> 
    </div> 
    <br> 
    <br> 
    <h1>Attachments:</h1> 
    <div id="loading"> Loading Attachments...</div> 
     <div id="no-attachment-found" hidden>No Attachment Found!!</div> 
     <table id="attachments" hidden> 
      <thead> 
        <tr> 
          <th>File</th> 
          <th>Created On</th>       
          <th>Actions</th> 
        </tr> 
      </thead> 
    <tbody> 
    </tbody> 
    </table> 
    </div> 
    
  13. Seleccione CTRL+S para guardar el código.

  14. Vuelva a la Página File Test, seleccione la lista y, a continuación seleccione Editar lista.

  15. Vaya a Acciones y luego habilite Editar registro.

  16. Para el Tipo de destino, seleccione Página web.

  17. Para Página web, seleccione Adjuntos.

  18. En Etiqueta para mostrar, escriba Cargar archivos adjuntos.

  19. Seleccione Listo.

  20. En la esquina superior derecha del estudio de diseño, seleccione Sincronizar para actualizar el sitio con las ediciones de código.

Paso 4: use la API para cargar, descargar y eliminar adjuntos

Para probar la funcionalidad de la API web:

  1. Seleccione Versión preliminar y luego seleccione Escritorio.

  2. Inicie sesión en su sitio con la cuenta de usuario que se le ha asignado el rol Usuario de API Azure File que creó anteriormente.

  3. Vaya a la página web Página File Test creada anteriormente.

  4. En el lado derecho, seleccione Cargar adjuntos.

  5. Elija un archivo e intente cargarlo.

  6. Intente descargar y eliminar un archivo existente.

Ahora que ha creado una página web con una muestra para cargar, descargar y eliminar adjuntos, puede personalizar los formularios y el diseño.

Códigos y mensajes de error

En la tabla siguiente se incluyen los diferentes códigos y mensajes de error que puede encontrar al usar la API web para cargar archivos en Azure:

Description Estado Http Código de error Mensaje de error.
No hay archivos adjuntos para cargar 400 FU00001 No se especifica el contenido del archivo
El identificador o nombre de la entidad proporcionado en los parámetros no es correcto 404 FU00002 No se ha encontrado el registro
El usuario no tiene permiso 403 FU00003 No tiene permisos para realizar esta operación
La extensión de archivo especificada no está configurada 400 FU00004 No se admite la extensión de archivo.
El tipo de archivo mime no se admite 400 FU00005 El mimetype no se admite
El tamaño del archivo es mayor que el configurado 400 FU00006 El tamaño del archivo es mayor que {0} MB
Las configuraciones de Azure son incorrectas 400 FU00007 Las configuraciones de Azure son incorrectas
Nombre de archivo no proporcionado 400 FU00008 Falta el encabezado x-ms-file-name en la solicitud
API no habilitado 501 FU00009 La API web de Azure no está habilitada para su uso
No es un archivo de Azure válido para actualizar/cargar/bloquear/eliminar/descargar 400 FU00010 El archivo solicitado no está disponible para {0}
La restricción de IP está habilitada en Azure en la cuenta de almacenamiento 403 FU00011 La restricción de IP está habilitada
El archivo no existe en Azure para descargarlo 400 FU00012 El archivo no existe
El tamaño del fragmento es superior a 100 mb 400 FU00013 El tamaño del fragmento es superior a 100 mb
No se indica el tamaño del archivo 400 FU00014 No se ha proporcionado el tamaño de archivo
Los tipos de archivo admitidos no se han establecido 400 FU00015 No se admite la extensión de archivo
Los tipos de mime admitidos no se han establecido 400 FU00016 No se admite el mimetype de archivo
Archivo de más de 128 MB sin fragmentación 400 FU00017 El tamaño del archivo es superior a 128 MB
Permiso no proporcionado a la aplicación Microsoft Entra 403 FU00018 La aplicación Microsoft Entra no tiene permisos para realizar esta operación
No existe el certificado para crear una conexión con Azure 400 FU00019 El certificado no existe
Cuando el identificador de inquilino, el identificador de cliente o la huella digital no están establecidos en la configuración de la aplicación 500 FU00020 Error interno del servidor
La extensión de archivo/tipo mime no se admite 400 FU00021 No se admite la extensión o el tipo MIME del archivo
El nombre de la cuenta o el nombre del contenedor no existe o no se proporciona 400 FU00022 Las configuraciones de Azure son incorrectas