Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este guia demonstra como implementar a API de Ficheiros do Azure. Estes passos permitem que os utilizadores ou visitantes do seu site vejam, editem, criem e eliminem anexos armazenados no Azure.
Nota
- Tamanho de Ficheiro do Azure de até 10 GB é suportado.
- Poderá alterar os nomes de coluna ou utilizar uma tabela diferente, ao mesmo tempo que segue os passos neste exemplo.
- Essas APIs só funcionam para registros já criados. Os anexos carregados através destas APIs serão associados a esse registo.
- Estas APIs efetuarão várias atualizações na entidade de nota (Anotação) à medida que os ficheiros são carregados em segmentos.
Pré-requisitos
Este passo a passo depende de uma tabela personalizada chamada Teste de Ficheiros. Pode criar uma tabela personalizada com o mesmo nome ou optar por utilizar outra tabela. Obtenha mais informações sobre como criar uma tabela personalizada em Criar e editar tabelas utilizando o Power Apps.
Passo 1: Criar definições do site
Antes de poder utilizar a API de Ficheiros do Azure, tem de ativar as definições de site necessárias com a aplicação Gestão do Portal. As definições do site dependem da tabela que pretende utilizar quando interage com a API de Ficheiros do Azure.
Abra a aplicação Gestão do Portal.
No painel esquerdo da aplicação Gestão do Portal, selecione Definições do Site.
Selecione Novo.
Para o Nome, introduza Site/FileManagement/EnableWebAPI.
Na lista do Site, selecione o seu registo do site.
Para o Valor, introduza verdadeiro.
Selecione Guardar e Fechar.
Adicione as seguintes definições de site:
Nome de definição do site DefaultValue Description Obrigatório Site/FileManagement/EnableWebAPI Ativa a API Web de gestão de ficheiros Sim Site/FileManagement/BlobStorageAccountName Nome da Conta de Armazenamento Sim Site/FileManagement/BlobStorageContainerName Nome do Contentor Sim Site/FileManagement/SupportedFileType Valores separados por vírgulas dos tipos de ficheiro. Por exemplo: .jpeg,.jpg Sim Site/FileManagement/SupportedMimeType ; tipos de MIME separados Sim Site/FileManagement/MaxFileSize 1048576 (1 GB) Tamanho máximo de ficheiro em KB Não Site/FileManagement/DownloadViaSASUri True (ativado por predefinição) Para decidir se pretende utilizar o URI SAS para transferir o ficheiro Não Site/FileManagement/DownloadSASUriExpiryTimeSpan 00:10:00 (10 minutos) Período máximo de expiração para URI SAS (necessário se 7 for true) Não Site/FileManagement/DownloadChunkSizeInKB 4096 (4 MB) Para decidir o tamanho do segmento a transferir (necessário se 7 for false) Não Adicione estas definições de site adicionais para ativar a API Web para anotações (notas):
Nome de definição do site valor Webapi/anotação/ativado verdadeiro Webapi/anotação/campos *
Passo 2: Configurar permissões
Terá de configurar permissões para que os utilizadores possam utilizar a caraterística API de Ficheiros do Azure. Neste exemplo, precisa de configurar ou de criar uma nova função da Web que utilize a API. De seguida, adicione as permissões de tabela para as tabelas Teste de Ficheiros e Nota e associe as permissões de tabela à função da Web. Por fim, atribui a função da Web aos utilizadores para permitir que utilizem a API.
Nota
A API segue as permissões de tabela do contexto da função da Web do utilizador autenticado ou da função da Web anónima. Considere se os utilizadores já têm uma função da Web que tem acesso às tabelas específicas no seu site requeridas pela API. Não precisa de criar funções da Web adicionais apenas para usar a API.
Criar uma função da Web
Se não tiver uma função da Web com permissões para a tabela necessária, utilize os passos seguintes para criar uma função da Web e atribuir permissões de tabela.
Abra a aplicação Gestão do Portal.
No painel esquerdo, na secção Segurança, selecione Funções da Web.
Selecione Novo.
Para o Nome, introduza Utilizador da API de Ficheiros do Azure ou qualquer nome que melhor reflita a função do utilizador que aceda a esta funcionalidade.
Na lista do Site, selecione o seu registo do site.
Selecione Guardar.
Criar permissões de tabela
Abra o Estúdio de design do Power Pages.
Selecione a área de trabalho Segurança.
Na secção Proteger, selecione Permissões de tabela.
Selecione Nova permissão
Para o Nome, introduza Permissão da Tabela Teste de Ficheiros.
Na lista Nome da Tabela, selecione Teste de Ficheiros (cr463_filetest).
Na lista Tipo de Acesso, selecione Acesso global.
Selecione os privilégios Ler e Anexar a.
Selecione + Adicionar funções e selecione a função da Web criada anteriormente.
Selecione Guardar.
Siga passos semelhantes para criar mais uma permissão para a tabela Nota (anotação) com os privilégios Escrever, Ler, Criar, Anexar e adicionar a mesma função da Web.
Adicionar contactos à função da Web
Abra a aplicação Gestão do Portal.
No painel esquerdo, na secção Segurança, selecione Contactos.
Selecione um contacto que pretende utilizar neste exemplo para a API.
Nota
Este contacto é a conta de utilizador utilizada neste exemplo para testar a API. Certifique-se de que seleciona o contacto correto no seu portal.
Selecione Relacionadas>Funções Web. Verifique se está a utilizar o formulário Contato do Portal. Se usar a Aplicação Power Pages Management, a subgrelha Funções da Web estará localizada na parte inferior do separador Geral.
Selecione Adicionar função Web existente.
Selecione a função de Utilizador da API de Ficheiros do Azure que criou anteriormente.
Selecione Adicionar.
Selecione Guardar e Fechar.
Adicionar permissões baseadas em funções para a aplicação Microsoft Entra
Inicie sessão no Azure onde a conta de armazenamento foi criada.
Aceda ao grupo de recursos, que contém a conta de armazenamento.
Selecione Controlo de acesso (IAM)>Adicionar>Adicionar atribuição de função.
Selecione a função Leitor e, em seguida, selecione Seguinte.
Selecione Utilizador, grupo ou principal de serviço e, em seguida, selecione + Selecionar membros.
No painel do lado direito, escolha a Aplicação empresarial do portal ao pesquisar o nome do site e, em seguida, selecione Selecionar. O nome da aplicação está no seguinte formato:
Portals-<site name>
Selecione Rever + atribuir>Rever + atribuir.
Aceda à conta de armazenamento e, em seguida, selecione Controlo de Acesso (IAM)>Adicionar>Adicionar atribuição de função.
Selecione a função Contribuidor de Dados de Blobs de Armazenamento e, em seguida, selecione Seguinte.
Selecione Utilizador, grupo ou principal de serviço e, em seguida, selecione + Selecionar membros.
No painel do lado direito, selecione a Aplicação empresarial do portal ao pesquisar o nome do site e, em seguida, selecione Selecionar.
Selecione Rever + atribuir>Rever + atribuir.
Passo 3: Criar uma página Web
Agora que ativou a API de Ficheiros do Azure e configurou as permissões de utilizador, crie uma página Web com uma lista de entidades para a tabela Teste de Ficheiros.
Abra o Estúdio de design do Power Pages.
Na área de trabalho Páginas, selecione + Página e selecione Outras formas de adicionar uma página.
Na caixa de diálogo Adicionar uma página, para o Nome da página, introduza Página de Teste de Ficheiros e selecione Iniciar em branco.
Selecione Adicionar.
Selecione Lista e, em seguida, adicione uma nova lista ou escolha uma lista existente para a tabela Teste de Ficheiros.
Crie uma página para anexos com o código de amostra a seguir para ver, editar, criar e eliminar registos.
Abra o Estúdio de design do Power Pages.
Na área de trabalho Páginas, selecione + Página e selecione Outras formas de adicionar uma página.
Na caixa de diálogo Adicionar uma página, para o Nome da página, introduza Anexos e selecione Iniciar em branco.
Selecione Adicionar.
Selecione a opção Editar código no canto superior direito.
Selecione Abrir o Visual Studio Code.
Copie o seguinte fragmento de código de amostra e cole-o entre as etiquetas
<div></div>
da secção de 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>
Selecione CTRL+S para guardar o código.
Regresse à Página Teste de Ficheiros, selecione a lista e, em seguida, selecione Editar lista.
Aceda a Ações e, em seguida, ative Editar registo.
Para o Tipo de Destino, selecione Página Web.
Para a Página Web, selecione Anexos.
Para Apresentar etiqueta, introduza Carregar anexos.
Selecione Concluído.
No canto superior direito do estúdio de design, selecione Sincronizar para atualizar o site com as edições de código.
Passo 4: Use a API carregar, transferir e eliminar anexos
Para testar a funcionalidade API Web:
Selecione Pré-visualização e, em seguida, selecione Ambiente de trabalho.
Inicie sessão no seu site com a conta de utilizador que está atribuída à função Utilizador da API de Ficheiros do Azure que criou anteriormente.
Aceda à página Web Página Teste de Ficheiros criado anteriormente.
No lado direito, selecione Carregar Anexos.
Escolha um ficheiro e tente carregá-lo.
Tente transferir e eliminar um ficheiro existente.
Agora que criou uma página Web com uma amostra para carregar, transferir e eliminar anexos, poderá personalizar os formulários e o esquema.
Códigos de erro e mensagens
A tabela a seguir inclui os diferentes códigos de erro e mensagens que poderá encontrar ao usar a API Web para carregar ficheiros para o Azure:
Description | Estado HTTP | Código de Erro | Mensagem de Erro |
---|---|---|---|
Nenhum ficheiro é anexado para carregar | 400 | FU00001 | O conteúdo do ficheiro não é especificado |
O ID da entidade ou o nome fornecido nos parâmetros não está correto | 404 | FU00002 | O registo não foi encontrado |
O utilizador não tem permissão | 403 | FU00003 | Não tem permissões para efetuar esta operação |
A extensão de ficheiro fornecida não está configurada | 400 | FU00004 | A extensão de ficheiro não é suportada. |
O tipo MIME de ficheiro não é suportado | 400 | FU00005 | O tipo MIME de ficheiro não é suportado |
O tamanho do ficheiro é maior que o configurado | 400 | FU00006 | O tamanho do ficheiro é maior que {0} MB |
As configurações do Azure estão incorretas | 400 | FU00007 | As configurações do Azure estão incorretas |
Nome do ficheiro não fornecido | 400 | FU00008 | O x-ms-file-name do cabeçalho está em falta no pedido |
API não ativada | 501 | FU00009 | A webapi do Azure não está ativada para utilização |
Não é um ficheiro do Azure válido para atualização/bloqueiodeatualização/eliminação/transferência | 400 | FU00010 | O ficheiro pedido não está disponível para {0} |
A restrição de IP está ativada no Azure na conta de armazenamento | 403 | FU00011 | A restrição de IP está ativada |
O ficheiro não existe no Azure para transferência | 400 | FU00012 | O ficheiro não existe |
O tamanho do segmento é maior que 100 mb | 400 | FU00013 | O tamanho do segmento é maior que 100 mb |
Tamanho do ficheiro não fornecido | 400 | FU00014 | Tamanho do ficheiro não fornecido |
Os tipos de ficheiro suportados não estão definidos | 400 | FU00015 | A extensão de nome de ficheiro não é suportada |
Os tipos de MIME suportados não estão definidos | 400 | FU00016 | O tipo de MIME do ficheiro não é suportado |
Mais de 128 mb de ficheiro sem segmentação | 400 | FU00017 | O tamanho do ficheiro é superior a 128 mb |
Permissão não fornecida à aplicação Microsoft Entra | 403 | FU00018 | A aplicação Microsoft Entra não tem permissões para efetuar esta operação |
O certificado não existe para criar ligação ao Azure | 400 | FU00019 | O certificado não existe |
Quando o ID do inquilino, o ID do cliente ou a thumbprint não estão definidos na definição da aplicação | 500 | FU00020 | Erro interno do servidor |
O tipo de MIME/extensão de ficheiro não suportado | 400 | FU00021 | Tipo de MIME ou extensão de nome de ficheiro não suportada |
O nome da conta ou o nome do contentor não existe ou não foi fornecido | 400 | FU00022 | As configurações do Azure estão incorretas |