Exemplo de Suplemento do SharePoint de carregamento de arquivos grandes
O exemplo Core.LargeFileUpload mostra como usar um suplemento hospedado pelo provedor para carregar arquivos no SharePoint e como ignorar o limite de carregamento de arquivo de 2-MB.
Use esta solução para carregar arquivos maiores do que 2 MB no SharePoint.
Este exemplo é executado como um aplicativo de console que carrega arquivos em uma biblioteca de documentos usando um dos seguintes métodos:
- O métodoSaveBinaryDirect forma a classeMicrosoft.SharePoint.Client.File.
- A propriedade ContentStream na classe FileCreationInformation.
- Os métodos StartUpload, ContinueUpload, e FinishUpload na classeArquivo.
A tabela a seguir lista os métodos de carregamento de arquivos que estão disponíveis e descrevem quando usar cada método.
Opções para carregar arquivos
Opção de carregamento de arquivo | Considerações | Quando você deve usar isso? | Plataformas com suporte |
---|---|---|---|
Propriedade Conteúdo na classe FileCreationInformation. | O tamanho máximo de arquivo que pode ser carregado é de 2 MB. O tempo limite ocorre após 30 minutos. | Use somente para carregar arquivos com menos de 2 MB. | SharePoint Server, SharePoint Online |
SaveBinaryDirect método na classe arquivo. |
Não há limites de tamanho de arquivo. O tempo limite ocorre após 30 minutos. | Apenas use este método se você estiver usando uma política de autenticação somente-usuário. Uma política de autenticação somente-usuário não está disponível em um suplemento do SharePoint, mas pode ser usada em suplementos nativos do dispositivo do Windows PowerShell e aplicativos de console do Windows. | SharePoint Server, SharePoint Online |
ContentStream propriedade na classe FileCreationInformation. |
Não há limites de tamanho de arquivo. O tempo limite ocorre após 30 minutos. | Recomendado para: - SharePoint Server – SharePoint Online quando ele for menor do que 10 MB. |
SharePoint Server, SharePoint Online |
Carregue um único arquivo como um conjunto de fragmentos usando os métodos StartUpload , ContinueUpload e FinishUpload na classe arquivo. |
Não há limites de tamanho de arquivo. O tempo limite ocorre após 30 minutos. Cada parte do arquivo deve carregar dentro de 30 minutos após a conclusão da parte anterior para evitar o tempo limite. | Recomendado para o SharePoint Online quando o arquivo for maior do que 10 MB. | SharePoint Online |
Antes de começar
Para começar, faça o download do suplemento de exemplo Core.LargeFileUpload no projeto Padrões e práticas do Desenvolvedor do Office 365 no GitHub.
Observação
The code in this article is provided as-is, without warranty of any kind, either express or implied, including any implied warranties of fitness for a particular purpose, merchantability, or non-infringement.
Usando o suplemento de exemplo Core.LargeFileUpload
Quando você iniciar o código a seguir, um aplicativo do console aparecerá. Você deverá fornecer suas credenciais de logon e uma URL de conjunto de sites do SharePoint Online para Office 365.
Depois da autenticação, o aplicativo de console exibirá uma exceção. A exceção ocorre quando o método UploadDocumentContent
no FileUploadService.cs tenta usar a propriedade FileCreationInformation.Content
para carregar um arquivo maior que 2 MB. UploadDocumentContentUploadDocumentContent
também cria uma biblioteca de documentos chamada Documentos caso ela ainda não exista. A biblioteca Documentosserá usada mais tarde no código a seguir.
public void UploadDocumentContent(ClientContext ctx, string libraryName, string filePath)
{
Web web = ctx.Web;
// Ensure that target library exists. Create if it is missing.
if (!LibraryExists(ctx, web, libraryName))
{
CreateLibrary(ctx, web, libraryName);
}
FileCreationInformation newFile = new FileCreationInformation();
// The next line of code causes an exception to be thrown for files larger than 2 MB.
newFile.Content = System.IO.File.ReadAllBytes(filePath);
newFile.Url = System.IO.Path.GetFileName(filePath);
// Get instances to the given library.
List docs = web.Lists.GetByTitle(libraryName);
// Add file to the library.
Microsoft.SharePoint.Client.File uploadFile = docs.RootFolder.Files.Add(newFile);
ctx.Load(uploadFile);
ctx.ExecuteQuery();
}
Em FileUploadService.cs, esse exemplo de código fornece três opções que você pode usar para carregar arquivos grandes para uma biblioteca de documentos:
- O método
File.SaveBinaryDirect
. - A propriedadeFileCreationInformation.ContentStream
FileCreationInformation.ContentStream
. - Os métodos
StartUpload
,ContinueUpload
eFinishUpload
na classe arquivo.
Em FileUploadService.cs, SaveBinaryDirect
usa o método Microsoft.SharePoint.Client.File.SaveBinaryDirect
com um objeto FileStream
para carregar arquivos em uma biblioteca de documentos.
public void SaveBinaryDirect(ClientContext ctx, string libraryName, string filePath)
{
Web web = ctx.Web;
// Ensure that the target library exists. Create it if it is missing.
if (!LibraryExists(ctx, web, libraryName))
{
CreateLibrary(ctx, web, libraryName);
}
using (FileStream fs = new FileStream(filePath, FileMode.Open))
{
Microsoft.SharePoint.Client.File.SaveBinaryDirect(ctx, string.Format("/{0}/{1}", libraryName, System.IO.Path.GetFileName(filePath)), fs, true);
}
}
Em FileUploadService.cs, UploadDocumentContentStream
usa a propriedade FileCreationInformation.ContentStream
com o objeto FileStream
para carregar um arquivo em uma biblioteca de documentos.
public void UploadDocumentContentStream(ClientContext ctx, string libraryName, string filePath)
{
Web web = ctx.Web;
// Ensure that the target library exists. Create it if it is missing.
if (!LibraryExists(ctx, web, libraryName))
{
CreateLibrary(ctx, web, libraryName);
}
using (FileStream fs = new FileStream(filePath, FileMode.Open))
{
FileCreationInformation flciNewFile = new FileCreationInformation();
// This is the key difference for the first case - using ContentStream property
flciNewFile.ContentStream = fs;
flciNewFile.Url = System.IO.Path.GetFileName(filePath);
flciNewFile.Overwrite = true;
List docs = web.Lists.GetByTitle(libraryName);
Microsoft.SharePoint.Client.File uploadFile = docs.RootFolder.Files.Add(flciNewFile);
ctx.Load(uploadFile);
ctx.ExecuteQuery();
}
}
Em FileUploadService.cs, UploadFileSlicePerSlice
carrega um arquivo grande em uma biblioteca de documentos como um conjunto de partes ou fragmentos. UploadFileSlicePerSlice
executa as seguintes tarefas:
- Obtém um novo GUID. Para carregar um arquivo em partes, você deve usar um GUID exclusivo.
- Calcula o tamanho das partes em bytes. Para calcular o tamanho do bloco em bytes,
UploadFileSlicePerSlice
usafileChunkSizeInMB
, que especifica o tamanho dos blocos individuais em MB. - Testa se o tamanho do arquivo a ser carregado (
fileSize
) é menor ou igual ao tamanho da parte (blockSize
).- Se
fileSize
é menor ou igual ao tamanho da parte, a amostra garante que o arquivo ainda será carregado usando a propriedadeFileCreationInformation.ContentStream
. Lembre-se de que o tamanho recomendado da parte é de 10 MB ou mais. - Se
fileSize
for maior do que o tamanho da parte:- A parte do arquivo é lido em
buffer
- Se o tamanho da parte for igual ao tamanho do arquivo, o arquivo todo foi lido. O bloco é copiado para o
lastBuffer
.lastBuffer
em seguida, o usa oFile.FinishUpload
para carregar o bloco.
- A parte do arquivo é lido em
- Se o tamanho da parte não é igual ao tamanho do arquivo, há mais de uma parte para ler o arquivo.
File.StartUpload
o é chamado para carregar o primeiro bloco.fileoffset
, que é usado como ponto de partida da próxima parte, é definido como a quantidade de bytes carregados da primeira parte. Quando a próxima parte é lida, se a última parte não tiver sido alcançada, File.ContinueUploadFile.ContinueUpload
é chamado para carregar a próxima parte do arquivo. O processo se repete até que a última parte seja lida. Quando a última parte for lidaFile.FinishUpload
carrega a última parte e compromete o arquivo. O conteúdo do arquivo será alterado em seguida, quando esse método estiver concluído.
- Se
Observação
Considere as seguintes práticas recomendadas:
- Use um mecanismo de repetição caso o carregamento seja interrompido. Quando um arquivo carregado for interrompido, o arquivo será chamado de arquivo não concluído. Você pode reiniciar o carregamento de um arquivo inacabado logo após o carregamento ser interrompido. Arquivos não concluídos são removidos do servidor entre 6 e 24 horas após o arquivo não terminado ter sido interrompido. O período de remoção pode mudar sem aviso prévio.
- Ao carregar um arquivo em partes para o SharePoint Online, um bloqueio é inserido no arquivo no SharePoint Online. Quando ocorrer uma interrupção, o arquivo permanecerá bloqueado para 15 minutos. Se a próxima parte do arquivo não for carregada no SharePoint Online dentro de 15 minutos, o bloqueio será removido. Após o bloqueio ser removido, você pode retomar o carregamento ou outro usuário pode começar a carregar o arquivo. Se outro usuário iniciar carregamento do arquivo, o arquivo não terminado será removido do SharePoint Online. O período de tempo que o bloqueio permanece em um arquivo depois do carregamento ser interrompido pode ser modificado sem aviso prévio.
- Você pode alterar o tamanho da parte. É recomendável usar um tamanho de parte de 10 MB.
- Retome uma parte interrompida ao controlar quais partes foram carregadas com êxito.
As partes devem ser carregadas em ordem sequencial. Você não pode carregar fatias ao mesmo tempo (por exemplo, usando uma abordagem multithread).
public Microsoft.SharePoint.Client.File UploadFileSlicePerSlice(ClientContext ctx, string libraryName, string fileName, int fileChunkSizeInMB = 3)
{
// Each sliced upload requires a unique ID.
Guid uploadId = Guid.NewGuid();
// Get the name of the file.
string uniqueFileName = Path.GetFileName(fileName);
// Ensure that target library exists, and create it if it is missing.
if (!LibraryExists(ctx, ctx.Web, libraryName))
{
CreateLibrary(ctx, ctx.Web, libraryName);
}
// Get the folder to upload into.
List docs = ctx.Web.Lists.GetByTitle(libraryName);
ctx.Load(docs, l => l.RootFolder);
// Get the information about the folder that will hold the file.
ctx.Load(docs.RootFolder, f => f.ServerRelativeUrl);
ctx.ExecuteQuery();
// File object.
Microsoft.SharePoint.Client.File uploadFile = null;
// Calculate block size in bytes.
int blockSize = fileChunkSizeInMB * 1024 * 1024;
// Get the information about the folder that will hold the file.
ctx.Load(docs.RootFolder, f => f.ServerRelativeUrl);
ctx.ExecuteQuery();
// Get the size of the file.
long fileSize = new FileInfo(fileName).Length;
if (fileSize <= blockSize)
{
// Use regular approach.
using (FileStream fs = new FileStream(fileName, FileMode.Open))
{
FileCreationInformation fileInfo = new FileCreationInformation();
fileInfo.ContentStream = fs;
fileInfo.Url = uniqueFileName;
fileInfo.Overwrite = true;
uploadFile = docs.RootFolder.Files.Add(fileInfo);
ctx.Load(uploadFile);
ctx.ExecuteQuery();
// Return the file object for the uploaded file.
return uploadFile;
}
}
else
{
// Use large file upload approach.
ClientResult<long> bytesUploaded = null;
FileStream fs = null;
try
{
fs = System.IO.File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using (BinaryReader br = new BinaryReader(fs))
{
byte[] buffer = new byte[blockSize];
Byte[] lastBuffer = null;
long fileoffset = 0;
long totalBytesRead = 0;
int bytesRead;
bool first = true;
bool last = false;
// Read data from file system in blocks.
while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
{
totalBytesRead = totalBytesRead + bytesRead;
// You've reached the end of the file.
if (totalBytesRead == fileSize)
{
last = true;
// Copy to a new buffer that has the correct size.
lastBuffer = new byte[bytesRead];
Array.Copy(buffer, 0, lastBuffer, 0, bytesRead);
}
if (first)
{
using (MemoryStream contentStream = new MemoryStream())
{
// Add an empty file.
FileCreationInformation fileInfo = new FileCreationInformation();
fileInfo.ContentStream = contentStream;
fileInfo.Url = uniqueFileName;
fileInfo.Overwrite = true;
uploadFile = docs.RootFolder.Files.Add(fileInfo);
// Start upload by uploading the first slice.
using (MemoryStream s = new MemoryStream(buffer))
{
// Call the start upload method on the first slice.
bytesUploaded = uploadFile.StartUpload(uploadId, s);
ctx.ExecuteQuery();
// fileoffset is the pointer where the next slice will be added.
fileoffset = bytesUploaded.Value;
}
// You can only start the upload once.
first = false;
}
}
else
{
if (last)
{
// Is this the last slice of data?
using (MemoryStream s = new MemoryStream(lastBuffer))
{
// End sliced upload by calling FinishUpload.
uploadFile = uploadFile.FinishUpload(uploadId, fileoffset, s);
ctx.ExecuteQuery();
// Return the file object for the uploaded file.
return uploadFile;
}
}
else
{
using (MemoryStream s = new MemoryStream(buffer))
{
// Continue sliced upload.
bytesUploaded = uploadFile.ContinueUpload(uploadId, fileoffset, s);
ctx.ExecuteQuery();
// Update fileoffset for the next slice.
fileoffset = bytesUploaded.Value;
}
}
}
} // while ((bytesRead = br.Read(buffer, 0, buffer.Length)) > 0)
}
}
finally
{
if (fs != null)
{
fs.Dispose();
}
}
}
return null;
}
Quando o código de exemplo for finalizado no seu site do Office 365, você pode ir para a biblioteca Documentos , escolhendo Documentos>Recentes. Verifique se a biblioteca Documentos contém três arquivos grandes.