> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Fichiers d'entité

> Lisez, écrivez et téléversez des fichiers de tout format attachés à une entité PlayFab, avec une boucle complète de fichiers d'entité en C# Unity couvrant la connexion, le chargement et le téléversement.

Les fichiers d'entité vous permettent de lire et d'écrire des fichiers de tout format attachés à une entité. L'exemple suivant illustre une boucle complète de fichiers d'entité, de la connexion au chargement d'un fichier, puis au téléversement d'un nouveau fichier.

```csharp theme={null}
#if !DISABLE_PLAYFABENTITY_API && !DISABLE_PLAYFABCLIENT_API

using PlayFab;
using PlayFab.Internal;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

public class EntityFileExample : MonoBehaviour
{
    public string entityId; // Id representing the logged in player
    public string entityType; // entityType representing the logged in player
    private readonly Dictionary<string, string> _entityFileJson = new Dictionary<string, string>();
    private readonly Dictionary<string, string> _tempUpdates = new Dictionary<string, string>();
    public string ActiveUploadFileName;
    public string NewFileName;
    public int GlobalFileLock = 0; // Kind of cheap and simple way to handle this kind of lock

    void OnSharedFailure(PlayFabError error)
    {
        Debug.LogError(error.GenerateErrorReport());
        GlobalFileLock -= 1;
    }

    void OnGUI()
    {
        if (!PlayFabClientAPI.IsClientLoggedIn() && GUI.Button(new Rect(0, 0, 100, 30), "Login"))
            Login();
        if (PlayFabClientAPI.IsClientLoggedIn() && GUI.Button(new Rect(0, 0, 100, 30), "LogOut"))
            PlayFabClientAPI.ForgetAllCredentials();

        if (PlayFabClientAPI.IsClientLoggedIn() && GUI.Button(new Rect(100, 0, 100, 30), "(re)Load Files"))
            LoadAllFiles();

        if (PlayFabClientAPI.IsClientLoggedIn())
        {
            // Display existing files
            _tempUpdates.Clear();
            var index = 0;
            foreach (var each in _entityFileJson)
            {
                GUI.Label(new Rect(100 * index, 60, 100, 30), each.Key);
                var tempInput = _entityFileJson[each.Key];
                var tempOutput = GUI.TextField(new Rect(100 * index, 90, 100, 30), tempInput);
                if (tempInput != tempOutput)
                    _tempUpdates[each.Key] = tempOutput;
                if (GUI.Button(new Rect(100 * index, 120, 100, 30), "Save " + each.Key))
                    UploadFile(each.Key);
                index++;
            }
            // Apply any changes
            foreach (var each in _tempUpdates)
                _entityFileJson[each.Key] = each.Value;

            // Add a new file
            NewFileName = GUI.TextField(new Rect(100 * index, 60, 100, 30), NewFileName);
            if (GUI.Button(new Rect(100 * index, 90, 100, 60), "Create " + NewFileName))
                UploadFile(NewFileName);
        }
    }

    void Login()
    {
        var request = new PlayFab.ClientModels.LoginWithCustomIDRequest
        {
            CustomId = SystemInfo.deviceUniqueIdentifier,
            CreateAccount = true
        };
        PlayFabClientAPI.LoginWithCustomID(request, OnLogin, OnSharedFailure);
    }
    void OnLogin(PlayFab.ClientModels.LoginResult result)
    {
        entityId = result.EntityToken.Entity.Id;
        entityType = result.EntityToken.Entity.Type;
    }

    void LoadAllFiles()
    {
        if (GlobalFileLock != 0)
            throw new Exception("This example overly restricts file operations for safety. Careful consideration must be made when doing multiple file operations in parallel to avoid conflict.");

        GlobalFileLock += 1; // Start GetFiles
        var request = new PlayFab.DataModels.GetFilesRequest { Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType } };
        PlayFabDataAPI.GetFiles(request, OnGetFileMeta, OnSharedFailure);
    }
    void OnGetFileMeta(PlayFab.DataModels.GetFilesResponse result)
    {
        Debug.Log("Loading " + result.Metadata.Count + " files");

        _entityFileJson.Clear();
        foreach (var eachFilePair in result.Metadata)
        {
            _entityFileJson.Add(eachFilePair.Key, null);
            GetActualFile(eachFilePair.Value);
        }
        GlobalFileLock -= 1; // Finish GetFiles
    }
    void GetActualFile(PlayFab.DataModels.GetFileMetadata fileData)
    {
        GlobalFileLock += 1; // Start Each SimpleGetCall
        PlayFabHttp.SimpleGetCall(fileData.DownloadUrl,
            result => { _entityFileJson[fileData.FileName] = Encoding.UTF8.GetString(result); GlobalFileLock -= 1; }, // Finish Each SimpleGetCall
            error => { Debug.Log(error); }
        );
    }

    void UploadFile(string fileName)
    {
        if (GlobalFileLock != 0)
            throw new Exception("This example overly restricts file operations for safety. Careful consideration must be made when doing multiple file operations in parallel to avoid conflict.");

        ActiveUploadFileName = fileName;

        GlobalFileLock += 1; // Start InitiateFileUploads
        var request = new PlayFab.DataModels.InitiateFileUploadsRequest
        {
            Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
            FileNames = new List<string> { ActiveUploadFileName },
        };
        PlayFabDataAPI.InitiateFileUploads(request, OnInitFileUpload, OnInitFailed);
    }
    void OnInitFailed(PlayFabError error)
    {
        if (error.Error == PlayFabErrorCode.EntityFileOperationPending)
        {
            // This is an error you should handle when calling InitiateFileUploads, but your resolution path might vary
            GlobalFileLock += 1; // Start AbortFileUploads
            var request = new PlayFab.DataModels.AbortFileUploadsRequest
            {
                Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
                FileNames = new List<string> { ActiveUploadFileName },
            };
            PlayFabDataAPI.AbortFileUploads(request, (result) => { GlobalFileLock -= 1; UploadFile(ActiveUploadFileName); }, OnSharedFailure); GlobalFileLock -= 1; // Finish AbortFileUploads
            GlobalFileLock -= 1; // Failed InitiateFileUploads
        }
        else
            OnSharedFailure(error);
    }
    void OnInitFileUpload(PlayFab.DataModels.InitiateFileUploadsResponse response)
    {
        string payloadStr;
        if (!_entityFileJson.TryGetValue(ActiveUploadFileName, out payloadStr))
            payloadStr = "{}";
        var payload = Encoding.UTF8.GetBytes(payloadStr);

        GlobalFileLock += 1; // Start SimplePutCall
        PlayFabHttp.SimplePutCall(response.UploadDetails[0].UploadUrl,
            payload,
            FinalizeUpload,
            error => { Debug.Log(error); }
        );
        GlobalFileLock -= 1; // Finish InitiateFileUploads
    }
    void FinalizeUpload(byte[] body) // body is unused in this example
    {
        GlobalFileLock += 1; // Start FinalizeFileUploads
        var request = new PlayFab.DataModels.FinalizeFileUploadsRequest
        {
            Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType },
            FileNames = new List<string> { ActiveUploadFileName },
        };
        PlayFabDataAPI.FinalizeFileUploads(request, OnUploadSuccess, OnSharedFailure);
        GlobalFileLock -= 1; // Finish SimplePutCall
    }
    void OnUploadSuccess(PlayFab.DataModels.FinalizeFileUploadsResponse result)
    {
        Debug.Log("File upload success: " + ActiveUploadFileName);
        GlobalFileLock -= 1; // Finish FinalizeFileUploads
    }
}
#endif
```

## Analyse de cet exemple

* `GlobalFileLock` est un moyen simpliste d'éviter les conflits de fichiers, conçu spécifiquement pour cet exemple.
  * Les actions indépendantes sur les fichiers ne posent aucun problème.
  * Chaque action sur un fichier nécessite de nombreuses étapes et plusieurs appels d'API; n'essayez donc pas d'accéder au même fichier de plusieurs façons en même temps.
  * Si vous êtes prudent, vous n'avez besoin d'aucun mécanisme de verrouillage.
  * Si vous souhaitez faire quelque chose de compliqué, votre mécanisme de verrouillage pourrait être beaucoup plus complexe.
* `OnGUI` est une méthode ancienne, mais très compacte, pour construire une interface utilisateur Unity entièrement dans un script.
  * Votre interface utilisateur sera bien meilleure et propre à votre jeu.
* Toutes les fonctionnalités PlayFab nécessitent *d'abord* une connexion ou une authentification.
* `LoadAllFiles()` fait exactement ce que son nom indique. Pour l'entité actuellement connectée, elle charge tous les fichiers enregistrés dans PlayFab.
  * Cette fonction nécessite plusieurs étapes :
    * Demander à PlayFab où se trouvent les fichiers,
    * Puis les télécharger séparément.
* `UploadFile(string fileName)` enregistre le fichier dans le service pour l'entité.
  * Par souci de simplicité, cet exemple enregistre un fichier à la fois, mais vous pouvez également téléverser des fichiers de façon atomique par lots.
  * Les étapes de cette opération sont les suivantes :
    * Initialiser une opération de téléversement atomique,
    * Téléverser tous les fichiers,
    * Finaliser l'opération de téléversement atomique.
  * L'entité ne considère pas le téléversement du fichier comme terminé et ne reflète aucune modification pour les autres appelants tant que l'opération de téléversement atomique n'a pas été finalisée avec succès.

## Game Manager et entités

Game Manager vous permet de manipuler les objets et les fichiers des joueurs. La vue d'ensemble du joueur a été mise à jour pour afficher à la fois les informations du compte de joueur du titre et du compte de joueur principal.

<img src="https://mintcdn.com/microsoft-4404708b/3hg2JQs0m7qmDqay/images/playfab/live-service-management/game-configuration/entities/tutorials/game-manager-entities-player-overview.png?fit=max&auto=format&n=3hg2JQs0m7qmDqay&q=85&s=ceac36d3b1e7fd248caeedbf4bea8055" alt="Game Manager : entités, vue d'ensemble du joueur" width="1800" height="1406" data-path="images/playfab/live-service-management/game-configuration/entities/tutorials/game-manager-entities-player-overview.png" />

De plus, l'onglet **Players** comprend désormais des sections distinctes pour les fichiers et les objets.

<img src="https://mintcdn.com/microsoft-4404708b/3hg2JQs0m7qmDqay/images/playfab/live-service-management/game-configuration/entities/tutorials/game-manager-entities-player-files.png?fit=max&auto=format&n=3hg2JQs0m7qmDqay&q=85&s=70b96669460d8bb673ec25fdbcd1bd41" alt="Game Manager : entités, fichiers et objets du joueur" width="1800" height="969" data-path="images/playfab/live-service-management/game-configuration/entities/tutorials/game-manager-entities-player-files.png" />

## Fonctionnalités associées

Les objets et fichiers d'entité sont utilisés dans plusieurs fonctionnalités PlayFab, chacune limitée à un type d'entité différent :

| Fonctionnalité | Types d'entités | Cas d'utilisation |
| - | - | - |
| [Configuration du serveur de jeu](/fr-CA/services/playfab/live-service-management/game-configuration) | `game_server` | Paramètres côté serveur et données faisant autorité côté serveur |
| [Données de titre](/fr-CA/services/playfab/live-service-management/game-configuration/titledata) | `namespace`, `title` | Configuration globale clé/valeur partagée entre tous les joueurs |
| [Données de joueur](/fr-CA/services/playfab/player-progression/player-data) | `title_player_account`, `master_player_account`, `character` | Stockage du profil, de la progression et des préférences de chaque joueur |
| [Groupes](/fr-CA/services/playfab/community/associations/groups) | `group` | Données partagées au sein d'un groupe de joueurs ou d'une guilde |


## Related topics

- [Démarrage rapide des entités](/fr-CA/services/playfab/live-service-management/game-configuration/entities/quickstart.md)
- [RGPD PlayFab - Supprimer les données des joueurs](/fr-CA/services/playfab/data-analytics/privacy-compliance/gdpr-deleting-player-data.md)
- [RGPD PlayFab - Exporter les données des joueurs](/fr-CA/services/playfab/data-analytics/privacy-compliance/gdpr-exporting-player-data.md)
- [Utiliser des objets d'entité pour stocker des données de joueur](/fr-CA/services/playfab/live-service-management/game-configuration/entities/entity-objects.md)
- [Vue d'ensemble de la configuration du serveur de jeu](/fr-CA/services/playfab/live-service-management/game-configuration/index.md)
