Partager via


Complément SharePoint : exemple de chargement de fichiers volumineux

L’exemple Core.LargeFileUpload vous montre comment utiliser un complément hébergé par le fournisseur pour télécharger des fichiers volumineux sur SharePoint et comment contourner la limite de téléchargement de fichiers < 2 Mo.

Utilisez cette solution si vous voulez télécharger des fichiers de plus de 2 Mo dans SharePoint.

Cet exemple s’exécute comme une application console qui télécharge des fichiers volumineux vers une bibliothèque de documents en utilisant l’une des méthodes suivantes :

Le tableau suivant répertorie les méthodes de téléchargement de fichier qui sont disponibles et quand utiliser chaque méthode décrite.

Options pour charger les fichiers

Option de chargement de fichiers Points à prendre en compte Quand devez-vous l’utiliser ? Plateformes prises en charge
La propriété Content sur la classe FileCreationInformation. 2 Mo est la taille de fichier maximale pour le téléchargement. Hors délai d’attente après 30 minutes. Permet de télécharger des fichiers de taille inférieure à 2 Mo uniquement. SharePoint Server, SharePoint Online
Méthode SaveBinaryDirect sur la classe File. Pas de limites de taille de fichier. Hors délai d’attente après 30 minutes. N’utilisez cette méthode que si vous utilisez une stratégie d’authentification utilisateur uniquement. Une stratégie d’authentification utilisateur uniquement n’est pas disponible dans un complément SharePoint, mais peut être utilisée dans des compléments de périphérique natifs, Windows PowerShell et des applications console Windows. SharePoint Server, SharePoint Online
Propriété ContentStream sur la classe FileCreationInformation. Pas de limites de taille de fichier. Hors délai d’attente après 30 minutes. Recommandé pour :
SharePoint Server
SharePoint Online quand la taille du fichier est inférieure à 10 Mo.
SharePoint Server, SharePoint Online
Téléchargez un fichier sous la forme d’un ensemble de blocs avec les méthodes StartUpload, ContinueUpload et FinishUpload sur la classe File. Pas de limites de taille de fichier. Hors délai d’attente après 30 minutes. Chaque bloc du fichier doit être téléchargé dans les 30 minutes suivant la fin du chargement du bloc précédent pour éviter l’expiration du délai d’attente. Recommandé pour SharePoint Online quand la taille du fichier est supérieure à 10 Mo. SharePoint Online

Avant de commencer

Pour commencer, téléchargez le complément exempleCore.LargeFileUpload à partir du projet Pratiques et modèles Office 365 Developer sur GitHub.

Remarque

Le code dans cet article est fourni tel quel, sans garantie d’aucune sorte, expresse ou implicite, y compris mais sans s’y limiter, aucune garantie implicite d’adéquation à un usage particulier, à une qualité marchande ou une absence de contrefaçon.

Utiliser le complément exemple de Core.LargeFileUpload

Lorsque vous démarrez cet exemple de code, une application console s’affiche. Vous devez fournir une URL de collection de sites SharePoint Online et vos informations d’identification pour Office 365.

Après l’authentification, l’application console affiche une exception. L’exception se produit lorsque la méthode UploadDocumentContent dans FileUploadService.cs tente d’utiliser la propriété FileCreationInformation.Content pour charger un fichier dont la taille est supérieure à 2 Mo. UploadDocumentContent crée également une bibliothèque de documents nommée Docs le cas échéant. La bibliothèque de documents Docs sert plus loin dans cet exemple de code.

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();
}

Dans FileUploadService.cs, cet exemple de code fournit trois options que vous pouvez utiliser pour charger des fichiers volumineux dans une bibliothèque de documents :

  • la méthode File.SaveBinaryDirect ;
  • la propriété FileCreationInformation.ContentStream ;
  • les méthodes StartUpload, ContinueUpload et FinishUpload sur la classe File.

Dans FileUploadService.cs, SaveBinaryDirect utilise la méthode Microsoft.SharePoint.Client.File.SaveBinaryDirect avec un objet FileStream pour charger des fichiers dans une bibliothèque de documents.

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);
  }
}

Dans FileUploadService.cs, UploadDocumentContentStream utilise la propriété FileCreationInformation.ContentStream avec l’objet FileStream pour charger un fichier dans une bibliothèque de documents.

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();
  }
}

Dans FileUploadService.cs, UploadFileSlicePerSlice charge un fichier volumineux vers une bibliothèque de documents sous la forme d’un ensemble de blocs ou fragments. UploadFileSlicePerSlice effectue les tâches suivantes :

  1. Obtient un nouveau GUID. Pour télécharger un fichier dans des segments, vous devez utiliser un GUID unique.
  2. Calcule la taille du bloc en octets. Pour calculer la taille du bloc en octets, UploadFileSlicePerSlice utilise fileChunkSizeInMB, qui spécifie la taille des blocs individuels en Mo.
  3. Teste si la taille du fichier à charger (fileSize) est inférieure ou égale à la taille d’un bloc (blockSize).
    • Si fileSize est inférieur ou égal à la taille du bloc, l’exemple vérifie que le fichier est toujours chargé à l’aide de la propriété FileCreationInformation.ContentStream. N’oubliez pas que la taille de bloc recommandée est de 10 Mo ou supérieure.
    • Si fileSize est supérieur à la taille du bloc :
      • un bloc du fichier est lu dans buffer.
      • Si la taille du bloc est égale à la taille de fichier, le fichier entier a été lu. Le bloc est copié dans lastBuffer. lastBuffer utilise ensuite File.FinishUpload pour charger le bloc.
    • Si la taille du bloc n’est pas égale à la taille de fichier, il y a donc plusieurs blocs à lire à partir du fichier. File.StartUpload est appelé pour charger le premier bloc. fileoffset, qui est utilisé comme point de départ du bloc suivant, est alors défini sur le nombre d’octets chargés à partir du premier bloc. Lorsque le bloc suivant est lu, si le dernier bloc n’a pas été atteint, File.ContinueUpload est appelé pour charger le bloc suivant du fichier. Le processus se répète jusqu'à ce qu’au dernier bloc. Lorsque le dernier bloc est lu, File.FinishUpload charge le dernier bloc et valide le fichier. Le contenu du fichier est modifié lorsque cette méthode est terminée.

Remarque

Notez les meilleures pratiques suivantes :

  • Utiliser un mécanisme de nouvelle tentative au cas où votre téléchargement est interrompu. Lorsqu’un fichier téléchargé est interrompu, ce fichier s’appelle un fichier non achevé. Vous pouvez redémarrer le téléchargement d’un fichier non achevé rapidement quand le téléchargement a été interrompu. Les fichiers non achevés sont supprimés du serveur entre 6 heures et 24 heures après l’interruption du chargement du fichier non achevé. Ce délai de suppression peut changer sans avertissement.
  • Lorsque vous chargez un fichier bloc à bloc dans SharePoint Online, un verrou est placé sur le fichier dans SharePoint Online. Lorsqu’une interruption se produit, le fichier reste verrouillé pendant 15 minutes. Si le bloc suivant du fichier n’est pas chargé dans SharePoint Online dans un délai de 15 minutes, le verrou est supprimé. Quand le verrou est supprimé, vous pouvez reprendre le téléchargement ou un autre utilisateur peut commencer à télécharger le fichier. Si un autre utilisateur commence à télécharger le fichier, votre fichier non achevé est supprimé de SharePoint Online. Ce délai de verrouillage du fichier après l’interruption du téléchargement peut changer sans avertissement.
  • Vous pouvez modifier la taille d’un bloc. Nous vous recommandons d’utiliser une taille de bloc de 10 Mo.
  • Reprendre un bloc interrompu en notant quels blocs ont été téléchargés correctement.

Les blocs doivent être téléchargés dans un ordre séquentiel. Vous ne pouvez pas charger des tranches simultanément (par exemple, en utilisant une approche 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;
}

Quand l’exemple de code a terminé, vous pouvez accéder dans votre site Office 365 à la bibliothèque de documents Docs en sélectionnant Récents>Docs. Vérifiez que la bibliothèque de documents Docs contient trois fichiers volumineux.

Voir aussi