Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
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.
Abra la aplicación Administración del portal.
En el panel izquierdo de la aplicación Administración del portal, seleccione Configuración del sitio.
Seleccione Nuevo.
En Nombre, escriba Site/FileManagement/EnableWebAPI.
En la lista Sitio web, seleccione el registro de su sitio web.
En el Valor, introduzca Verdadero.
Seleccione Guardar y cerrar.
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 Sí Site/FileManagement/BlobStorageAccountName Nombre de la cuenta de almacenamiento Sí Site/FileManagement/BlobStorageContainerName Nombre de contenedor Sí Site/FileManagement/SupportedFileType Valores separados por comas de los tipos de archivo. Por ejemplo: .jpeg, .jpg Sí Site/FileManagement/SupportedMimeType ; separados tipos MIME Sí 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 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.
Abra la aplicación Administración del portal.
En el panel izquierdo, dentro de la sección Seguridad, seleccione Roles web.
Seleccione Nuevo.
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.
En la lista Sitio web, seleccione el registro de su sitio web.
Seleccione Guardar.
Crear permisos de tabla
Abra el Estudio de diseño de Power Pages.
Seleccione el espacio de trabajo Seguridad.
En la sección Proteger, seleccione Permisos de tabla.
Seleccione Nuevo permiso.
Para el Nombre, introduzca Permiso de tabla File Test.
En la lista Nombre de tabla, seleccione File Test (cr463_filetest).
En la lista Tipo de acceso, seleccione Acceso global.
Seleccione los privilegios Leery Anexar.
Seleccione + Agregar roles y seleccione el rol web que creó anteriormente.
Seleccione Guardar.
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
Abra la aplicación Administración del portal.
En el panel izquierdo, dentro de la sección Seguridad, seleccione Contactos.
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.
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.
Seleccione Agregar rol web existente.
Seleccione el rol Usuario API Azure File que creó anteriormente.
Seleccione Agregar.
Seleccione Guardar y cerrar.
Agregar permisos basados en roles para la aplicación Microsoft Entra
Inicie sesión en Azure donde se creó la cuenta de almacenamiento.
Vaya al grupo de recursos que contiene la cuenta de almacenamiento.
Seleccione Control de acceso (IAM)>Agregar>Agregar asignación de roles.
Seleccione el rol Lector y después Siguiente.
Seleccione Usuario, grupo o entidad de servicio y, a continuación, seleccione + Seleccionar miembros.
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>
Seleccione Revisar + asignar>Revisar + asignar.
Vaya a la cuenta de almacenamiento y seleccione Control de acceso (IAM)>Agregar>Agregar asignación de rol.
Seleccione el rol Datos de blob de almacenamiento Colaborador y seleccione Siguiente.
Seleccione Usuario, grupo o entidad de servicio y, a continuación, seleccione + Seleccionar miembros.
En el lado derecho, seleccione la aplicación Portal Enterprise buscando el nombre del sitio y luego seleccione Seleccionar.
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.
Abra el Estudio de diseño de Power Pages.
En el espacio de trabajo Páginas, seleccione + Página y seleccione Otras formas de agregar una página.
En el diálogo Agregar una página, para Nombre de página, introduzca Página File Test y después Empezar desde cero.
Seleccione Agregar.
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.
Abra el Estudio de diseño de Power Pages.
En el espacio de trabajo Páginas, seleccione + Página y seleccione Otras formas de agregar una página.
En el diálogo Agregar una página, para Nombre de página, introduzca Adjuntos y después Empezar desde cero.
Seleccione Agregar.
Seleccione la opción Editar código en la esquina superior derecha.
Seleccione Abrir Visual Studio Code.
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>
Seleccione CTRL+S para guardar el código.
Vuelva a la Página File Test, seleccione la lista y, a continuación seleccione Editar lista.
Vaya a Acciones y luego habilite Editar registro.
Para el Tipo de destino, seleccione Página web.
Para Página web, seleccione Adjuntos.
En Etiqueta para mostrar, escriba Cargar archivos adjuntos.
Seleccione Listo.
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:
Seleccione Versión preliminar y luego seleccione Escritorio.
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.
Vaya a la página web Página File Test creada anteriormente.
En el lado derecho, seleccione Cargar adjuntos.
Elija un archivo e intente cargarlo.
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 |