//Upload stuff: private readonly Dictionary _entityFileJson = new Dictionary(); public string ActiveUploadFileName; public int GlobalFileLock = 0; private List uploadQueue; private bool uploadCoroutineActive; private float uploadStartTime; private bool uploading; public void AddEntityFileAndUpload(string fileName, string contents) { if (string.IsNullOrEmpty(contents)) return; if (_entityFileJson.ContainsKey(fileName)) { _entityFileJson[fileName] = contents; } else { _entityFileJson.Add(fileName, contents); } if (GlobalFileLock == 0) { QueueUpload(fileName); } } public void RemoveFileFromUploadQueue(string fileName) { if (_entityFileJson != null && _entityFileJson.ContainsKey(fileName)) { _entityFileJson.Remove(fileName); } if (uploadQueue != null && uploadQueue.Contains(fileName)) uploadQueue.Remove(fileName); } public void QueueUpload(string fileName) { if (uploadQueue == null) { uploadQueue = new List(); } if (!uploadQueue.Contains(fileName)) uploadQueue.Add(fileName); } IEnumerator UploadCoroutine() { uploadCoroutineActive = true; int k = 0; yield return new WaitForSecondsRealtime(0.5f); float startTime = Time.time; while (GlobalFileLock != 0) yield return null; UploadFiles(uploadQueue); Debug.Log("API successfully uploaded " + k + " files, took " + (Time.time - startTime).ToString() + " seconds"); uploadCoroutineActive = false; } public void UploadFiles() { if (GlobalFileLock == 0 && ((Time.time > 15 && Time.time > (lastUploadTime+15)) || lastUploadTime == 0)) UploadFiles(uploadQueue); } void UploadFiles(List fileNames) { if (GlobalFileLock != 0 && !uploading) 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."); else { if (LoggedIn) { uploading = true; uploadStartTime = Time.time; GlobalFileLock += 1; // Start InitiateFileUploads var request = new PlayFab.DataModels.InitiateFileUploadsRequest { Entity = new PlayFab.DataModels.EntityKey {Id = entityId, Type = entityType}, FileNames = fileNames, }; Debug.Log("API Upload starting for " + uploadQueue); 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 may vary GlobalFileLock += 1; // Start AbortFileUploads var request = new PlayFab.DataModels.AbortFileUploadsRequest { Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType }, FileNames = uploadQueue// new List { ActiveUploadFileName }, }; PlayFabDataAPI.AbortFileUploads(request, (result) => { GlobalFileLock -= 1; }, OnSharedFailure); GlobalFileLock -= 1; // Finish AbortFileUploads GlobalFileLock -= 1; // Failed InitiateFileUploads } else OnSharedFailure(error); } void OnInitFileUpload(PlayFab.DataModels.InitiateFileUploadsResponse response) { Debug.Log("API OnInitFileUpload " + response.UploadDetails); queueItemsUploaded = 0; GlobalFileLock += 1; // Start SimplePutCall for (int i = 0; i < uploadQueue.Count; i++) { string payloadStr; if (!_entityFileJson.TryGetValue(uploadQueue[i], out payloadStr)) payloadStr = "{}"; var payload = Encoding.UTF8.GetBytes(payloadStr); PlayFabHttp.SimplePutCall(response.UploadDetails[i].UploadUrl, payload, success => { FinalizeUpload(); }, error => { Debug.Log(error); } ); } GlobalFileLock -= 1; // Finish InitiateFileUploads } private int queueItemsUploaded = 0; void FinalizeUpload() { Debug.Log("API FinalizeUpload"); queueItemsUploaded++; if (queueItemsUploaded >= uploadQueue.Count) { lastUploadTime = Time.time; GlobalFileLock += 1; // Start FinalizeFileUploads var request = new PlayFab.DataModels.FinalizeFileUploadsRequest { Entity = new PlayFab.DataModels.EntityKey {Id = entityId, Type = entityType}, FileNames = uploadQueue, }; PlayFabDataAPI.FinalizeFileUploads(request, OnUploadSuccess, OnSharedFailure); GlobalFileLock -= 1; // Finish SimplePutCall // uploading = false; } } void OnUploadSuccess(PlayFab.DataModels.FinalizeFileUploadsResponse result) { Debug.Log("API successfully uploaded files, took " + (Time.time - uploadStartTime).ToString() + " seconds"); Debug.Log("File upload success: " + uploadQueue); GlobalFileLock -= 1; // Finish FinalizeFileUploads uploading = false; } void OnSharedFailure(PlayFabError error) { Debug.LogError("API: " + error.GenerateErrorReport()); // GlobalFileLock = 0; if (LoggedIn) { StartCoroutine(UploadFailWaiter()); } } IEnumerator UploadFailWaiter() { if (uploadQueue.Count > 0) { var request = new PlayFab.DataModels.AbortFileUploadsRequest { Entity = new PlayFab.DataModels.EntityKey {Id = entityId, Type = entityType}, FileNames = uploadQueue // new List { ActiveUploadFileName }, }; PlayFabDataAPI.AbortFileUploads(request, (result) => { Debug.Log("successfully aborted upload"); }, (error) => { Debug.Log("failed to abort upload"); OnSharedFailure(error); }); // Finish AbortFileUploads } yield return new WaitForSecondsRealtime(15); uploadQueue.Clear(); GlobalFileLock = 0; uploading = false; }