Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Objetivo
Este tutorial irá orientá-lo ao longo da migração de conteúdos de Armazenamento de Blobs do Azure (ABS) para o SharePoint Embedded (SPE) com C#. Isto é útil para clientes que têm 500 documentos no contentor de armazenamento de blobs.
Pré-requisitos
Um Microsoft Entra ID registo de aplicação. Veja Registar uma aplicação.
O seu inquilino Microsoft Entra ID tem uma subscrição do Microsoft 365.
Um inquilino Microsoft Entra ID. Se não tiver um inquilino, crie uma conta gratuita do Azure para obter uma subscrição gratuita.
Uma conta com, pelo menos, a função Administrador Global ou Administrador Incorporado do SharePoint.
.NET Core SDK versão 8.0.303
Ambiente do Dotnet para executar a aplicação de exemplo
- Pode ser executado no Windows, Linux e macOS
Contentor do SharePoint Embedded
- Para obter mais informações sobre como configurar um contentor SPE
Armazenamento de Blobs do Azure contentor
- Para obter mais informações sobre como configurar um contentor de ABS
Autenticação
Azure Storage Blob
- Credenciais – URL da Assinatura de Acesso Partilhado (SAS) ao nível do contentor.
- Permissão - Leitura e Lista
SharePoint Inserido
Uma conta do Azure
Um Inquilino do SharePoint onde irá criar os seus contentores e o respetivo ID de Inquilino
Um ID de aplicação integrado (por vezes denominado ID de cliente) e o ContainerTypeId correspondente
Crie um novo Registo de Aplicação no portal Microsoft Entra ID.
No Registo de Aplicações, adicione uma nova plataforma de aplicações da Consola & Móvel no portal de Autenticação do Registo de Aplicações do Microsoft Entra ID
Um ContainerType
Um Contentor
Ter a aplicação registada no inquilino que está a consumir (mesmo que o proprietário da aplicação seja o mesmo que o consumidor)
Ter o containerType registado no inquilino que está a consumir (mesmo que o proprietário do CT seja o mesmo que o consumidor)
Consumir o nome de utilizador do inquilino e as credenciais de palavra-passe – será necessário para autenticar o cliente do Microsoft Graph
Permissão – "User.Read", "FileStorageContainer.Selected"
Migrar Dados de Armazenamento de Blobs do Azure contentor para o contentor Do SharePoint Embedded
Descrição
Esta secção fornece fragmentos de código sobre como realizar a migração. Toda a validação foi removida para legibilidade.
Ligar ao Contentor do Armazenamento de Blobs do Azure
_containerClient = new BlobContainerClient(new Uri(_containerLevelSASUrl));
Ligar ao SharePoint Embedded
string[] _scopes = { "User.Read", "FileStorageContainer.Selected" };
InteractiveBrowserCredentialOptions interactiveBrowserCredentialOptions = new InteractiveBrowserCredentialOptions()
{
ClientId = clientId,
RedirectUri = new Uri("http://localhost"),
};
InteractiveBrowserCredential interactiveBrowserCredential = new InteractiveBrowserCredential(interactiveBrowserCredentialOptions);
_graphClient = new GraphServiceClient(interactiveBrowserCredential, scopes, null);
// Will open up a browser to provide your consuming tenant admin credentials
var user = await _graphClient.Me.GetAsync();
Obter a lista de blobs
var blobs = new List<string>();
await foreach (var blobItem in _containerClient.GetBlobsAsync())
{
blobs.Add(blobItem.Name);
}
return blobs;
Conjunto de threads
private CountdownEvent _countdown;
// This is how the thread pool knows how many files are being migrated
_countdown = new CountdownEvent(blobs.Count);
Estrutura de Ficheiros
public class FileStructure
{
public string blobName { get; set; }
public string parentFolderId { get; set; }
}
Percorrer lista de blobs
// It creates a new folder in the destination. The name of the folder is the blob's container name.
// root means it is the root of the document library.
// If you want to copy it to another drive item, you can put the drive item ID here.
containerFolder = await _graphClient.CreateFolder(_containerName, "root");
// Traverse the blob list
foreach (var blobName in fileList)
{
FileStructure fs = new FileStructure() { blobName = blobName };
// This function parses the flat file into the folder hierarchy and creates the folder structure in the destination. It will retrieve the parentFolderId that the file should be copied to.
// If you are going to copy it to root you can comment this line out. The parentFolderId will be containerFolder.Id
fs.parentFolderId = TraverseBlobName(fs, containerFolder.Id)
// This is where the thread pool happens.
// It takes in a callback function and an Object parameter.
ThreadPool.QueueUserWorkItem(MigrateFile, fs);
}
// Call so the program doesn't end, it waits for all the files to be processed
_countdown.Wait();
Percorrer o nome do blob
// Parse for folder path not including the file name and put it in an array
var pathSegments = filePath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
string[] directoriesParts = pathSegments.Take(pathSegments.Length - 1).ToArray();
// Traverse the folder listing and create 1 folder at a time
string relativePath = _containerName;
string newFolderId = parentFolderId;
foreach (string folderName in directoriesParts)
{
string newPath = relativePath + _separator + folderName;
...
DriveItem subFolder = await _graphClient.CheckIfItemExists(folderName, newFolderId);
if (subFolder == null)
{
subFolder = await _graphClient.CreateFolder(folderName, newFolderId);
...
}
newFolderId = subFolder.Id;
relativePath = newPath;
}
return newFolderId;
Verificar se o item existe
var item = await _graphClient.Drives[_containerId].Items[parentFolderId].ItemWithPath(itemPath).GetAsync();
Criar pasta
var folder = new DriveItem
{
Name = folderName,
Folder = new Folder(),
AdditionalData = new Dictionary<string, object>()
{
{ "@microsoft.graph.conflictBehavior", "fail" }
}
};
var createdFolder = await _graphClient.Drives[_containerId].Items[parentFolderId].Children.PostAsync(folder);
Migrar Ficheiro
// The parameter must be of type Object.
internal async void MigrateFile(Object stateInfo)
{
var fileStructure = (FileStructure)stateInfo;
// Check if the file exists in the destination. If it exists
// - don't upload
// - check if the file is newer in the source than the destination - then upload
...
// Migrate the file
// This is where you download the blob as a stream from abs (code below)
...
// Then upload the stream to SPE (code below)
...
// Signal the countdown event that a file has been migrated
_countdown.Signal();
return;
}
Transferir do blob de ABS como um Stream
BlobClient blobClient = _containerClient.GetBlobClient(blobName);
MemoryStream memoryStream = new MemoryStream();
await blobClient.DownloadToAsync(memoryStream);
memoryStream.Position = 0; // Reset the stream position to the beginning
Carregar o Stream para o SPE
int _maxChunkSize = 320 * 1024;
var uploadSessionRequestBody = new CreateUploadSessionPostRequestBody()
{
AdditionalData = new Dictionary<string, object>
{
// Fail is set here, so it doesn't get upload again if it already exist
{ "@microsoft.graph.conflictBehavior", "fail" }
}
};
var uploadSession = await _graphClient.Drives[_containerId]
.Items[parentFolderId]
.ItemWithPath(fileName)
.CreateUploadSession
.PostAsync(uploadSessionRequestBody);
// The stream is the same stream from the downloading the blob
var fileUploadTask = new LargeFileUploadTask<DriveItem>(uploadSession, memoryStream, _maxChunkSize, _graphClient.RequestAdapter);
IProgress<long> progress = new Progress<long>(prog => Console.WriteLine($"Uploaded {fileName} {prog} bytes"));
// Check uploadResult.UploadSucceeded to see if it is successful
var uploadResult = await fileUploadTask.UploadAsync(progress);
Descrição geral da aplicação de exemplo
Descrição
Uma aplicação de exemplo denominada MigrateABStoSPE concebida para migrar ficheiros de um contentor de Armazenamento de Blobs do Azure (ABS) para um contentor do SharePoint Embedded (SPE). Os fragmentos de código fornecidos no contentor Migrar Dados de Armazenamento de Blobs do Azure para o SharePoint Embedded são provenientes da aplicação de exemplo.
Utiliza bibliotecas Azure.Storage.Blobs e Newtonsoft.Json para trabalhar com dados ABS e JSON, respetivamente. A aplicação autentica-se com ABS e SPE com credenciais de cliente e efetua a migração de ficheiros.
Pacotes
- SDK do Microsoft Graph (versão 5.56.0)
- Azure.Identity (versão 1.12.0)
- Azure.Storage.Blobs (versão 12.21.0)
- CommandLineParser (versão 2.9.1)
- Newtonsoft.Json (13.0.3)
Fora do Âmbito
- Como lidar com ficheiros que já existem no destino – falha, não substitui nem muda o nome
- Como lidar com ABS versão mais recente do que o destino – falha porque o ficheiro já existe no destino
Executar a aplicação de exemplo
Abra um terminal ou linha de comandos.
Navegue para o diretório onde se encontra o ficheiro Program.cs.
Certifique-se de que tem o SDK .NET Core instalado no seu computador. Pode marcar isto ao executar o comando dotnet --version no terminal. Se o comando não for reconhecido, pode transferir e instalar o SDK .NET Core a partir do site oficial da Microsoft.
Depois de confirmar que o SDK .NET Core está instalado, pode criar a aplicação ao executar o comando
dotnet build. Isto irá compilar o código e gerar os binários necessários.Após a conclusão do processo de compilação, pode executar a aplicação ao executar a execução do dotnet de comando, seguido dos argumentos necessários. Os argumentos necessários são:
- O URL de SAS ao nível do contentor: este é um URL de SAS ao nível do contentor de Blobs do Azure. Fornece acesso ao contentor e aos respetivos blobs.
- O ID do inquilino do SPE: este é o inquilino no qual está a autenticar no SPE.
- O ID de cliente SPE: este é o cliente no qual está a autenticar no SPE.
- O ID do contentor SPE: este é o contentor para o qual está a migrar conteúdos no SPE. Para obter mais informações sobre como obter o ID de contentor
- (opcional) Nome do ficheiro com caminho completo que contém a lista de blobs.
- (opcional) Nome do ficheiro com caminho completo onde a saída de blobs falhou.
Por exemplo, o comando para executar a aplicação com os argumentos necessários teria o seguinte aspeto:
dotnet run Program.cs -- --sasurl "<sas url>" --tenantid "<tenant id>" --clientid "<client id>" --containerid "<container id>" [ --blobfile "<file name>" --outputfile "<file name>" ]
Estrutura de Itens de Blobs e SPE
ABS contentor não aderir a uma estrutura de pastas, todos os blobs são armazenados numa estrutura de listagem simples. Ao migrar para o SPE, a aplicação de exemplo analisa o nome do blob e cria a estrutura de pastas no ID de contentor fornecido, com o nome do contentor como a pasta superior. Se estiver a migrar para a pasta raiz, pode ignorar esta secção.
Fonte
- Nome do Contentor: Contentor1
- Nome do blob: FolderA/blob1.txt
- Nome do blob: FolderA/FolderB/blob2.txt
- Nome do blob: FolderA/FolderB/FolderC/blob3.txt
Destino
- Pasta Item de Unidade
- Contentor1
- PastaA
- blob1.txt
- PastaB
- blob2.txt
- PastaC
- blob3.txt
- PastaA
- Contentor1
Processamento de Erros e Exceções
Problemas comuns
O ficheiro já existe no destino
- Esta aplicação verifica se o nome do ficheiro existe no destino antes de ser carregado. Se existir um ficheiro com exatamente o mesmo nome, não fará o carregamento novamente. Será impressa para eliminar uma mensagem de que o ficheiro já existe. Para o corrigir, pode eliminar o ficheiro do destino ou alterar o conflictBehavior para substituir e não chamar
CheckIfItemExistsno carregamento.
- Esta aplicação verifica se o nome do ficheiro existe no destino antes de ser carregado. Se existir um ficheiro com exatamente o mesmo nome, não fará o carregamento novamente. Será impressa para eliminar uma mensagem de que o ficheiro já existe. Para o corrigir, pode eliminar o ficheiro do destino ou alterar o conflictBehavior para substituir e não chamar
O ficheiro para a lista de blobs não foi encontrado
O formato da lista de blobs - um blob por linha, sem aspas à volta do nome do blob
Não dá permissão suficiente para aceder ao contentor de ABS
- As permissões mínimas são Leitura e Lista
Não dá permissões suficientes ao contentor SPE
- O âmbito necessário é "User.Read" e "FileStorageContainer.Selected"
- Não se esqueça de conceder o consentimento do administrador
- Lembre-se de criar a aplicação da plataforma da consola do & móvel
Testar a Migração
Verificação
- Quando o ficheiro está em fila de espera, será impresso para stdout
- Irá imprimir as estatísticas do total de blobs que foram processados: total, êxito, existe no destino e falhou.
- Se existirem erros, enviará a lista de blobs com falhas para um ficheiro. O nome do ficheiro será impresso para stdout. Também irá imprimir um comando para uma nova execução incremental.
Conclusão
Resumo
Neste tutorial, explorámos como migrar conteúdos de ABS contentor para o contentor SPE. Ao seguir os passos descritos, escrever a sua própria aplicação para migrar conteúdo deve ser fácil.
Para recapitular, nós:
- Autenticado com o ABS e o Graph
- Como utilizar um conjunto de threads para colocar em fila a migração do blob
- Verificar se o item existe no destino
- Obteve a lista de blobs do ABS contentor
- Carregou o blob para o contentor SPE
Compreender estes passos é fundamental para migrar conteúdos de ABS contentor para o contentor SPE. Agora, experimente implementar estes passos nos seus próprios projetos e veja a diferença que faz!
Codificação feliz!
Próximas etapas
- Para obter mais informações sobre o Armazenamento de Blobs, veja a documentação do Armazenamento de Blobs.
- Para obter mais informações sobre o SPE, veja a documentação do SharePoint Embedded.
Apêndice
Repositório de Código
A aplicação de exemplo pode ser encontrada no repositório Exemplos Incorporados do SharePoint.