diff --git a/src/Api/PubnubApi/EndPoint/Files/DownloadFileOperation.cs b/src/Api/PubnubApi/EndPoint/Files/DownloadFileOperation.cs index ef482217d..014d16dc1 100644 --- a/src/Api/PubnubApi/EndPoint/Files/DownloadFileOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Files/DownloadFileOperation.cs @@ -1,264 +1,204 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif using PubnubApi.Security.Crypto; using PubnubApi.Security.Crypto.Cryptors; -using static System.Net.WebRequestMethods; -using System.Threading.Channels; namespace PubnubApi.EndPoint { - public class DownloadFileOperation : PubnubCoreBase - { - private readonly PNConfiguration config; - private readonly IJsonPluggableLibrary jsonLibrary; - private readonly IPubnubUnitTest unit; - private readonly IPubnubLog pubnubLog; - - private PNCallback savedCallback; - private Dictionary queryParam; - - private string channelName; - private string currentFileId; - private string currentFileName; - private string currentFileCipherKey; - - public DownloadFileOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) - { - config = pubnubConfig; - jsonLibrary = jsonPluggableLibrary; - unit = pubnubUnit; - pubnubLog = log; - - if (instance != null) - { - if (!ChannelRequest.ContainsKey(instance.InstanceId)) - { - ChannelRequest.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - if (!ChannelGroupInternetStatus.ContainsKey(instance.InstanceId)) - { - ChannelGroupInternetStatus.GetOrAdd(instance.InstanceId, new ConcurrentDictionary()); - } - } - } - - public DownloadFileOperation Channel(string channel) - { - this.channelName = channel; - return this; - } - - public DownloadFileOperation FileId(string fileId) - { - this.currentFileId = fileId; - return this; - } - - public DownloadFileOperation FileName(string fileName) - { - this.currentFileName = fileName; - return this; - } - - public DownloadFileOperation CipherKey(string cipherKeyForFile) - { - this.currentFileCipherKey = cipherKeyForFile; - return this; - } - - public DownloadFileOperation QueryParam(Dictionary customQueryParam) - { - this.queryParam = customQueryParam; - return this; - } - - public void Execute(PNCallback callback) - { - if (callback == null) - { - throw new ArgumentException("Missing callback"); - } - - if (string.IsNullOrEmpty(this.currentFileId)) - { - throw new ArgumentException("Missing File Id"); - } - if (string.IsNullOrEmpty(this.currentFileName)) - { - throw new ArgumentException("Missing File Name"); - } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - this.savedCallback = callback; - ProcessFileDownloadRequest(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - this.savedCallback = callback; - ProcessFileDownloadRequest(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - public async Task> ExecuteAsync() - { - return await ProcessFileDownloadRequest(this.queryParam).ConfigureAwait(false); - } - - internal void Retry() - { -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - ProcessFileDownloadRequest(this.queryParam, savedCallback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => - { - ProcessFileDownloadRequest(this.queryParam, savedCallback); - }) - { IsBackground = true }.Start(); -#endif - } - - private void ProcessFileDownloadRequest(Dictionary externalQueryParam, PNCallback callback) - { - var requestParameter = CreateRequestParameter(); - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetFileUrlOrDeleteReqest(Constants.GET, "", this.channelName, this.currentFileId, this.currentFileName, externalQueryParam, PNOperationType.PNDownloadFileOperation); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNDownloadFileOperation; - requestState.PubnubCallback = callback; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - byte[] item1Bytes = null; - UrlProcessRequestForStream(request, requestState, false,"").ContinueWith(r => - { - item1Bytes = r.Result.Item1; - if (item1Bytes != null) - { - byte[] outputBytes = null; - if (string.IsNullOrEmpty(this.currentFileCipherKey) && string.IsNullOrEmpty(config.CipherKey) && config.CryptoModule == null) - { - outputBytes = item1Bytes; - } - else - { - CryptoModule currentCryptoModule = !string.IsNullOrEmpty(this.currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(this.currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null)); - try - { - outputBytes = currentCryptoModule.Decrypt(item1Bytes); - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Stream length (after Decrypt)= {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), item1Bytes.Length), config.LogVerbosity); - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine("{0}\nMessage might be not encrypted, returning as is...", ex.ToString()); - outputBytes = item1Bytes; - } - } - PNDownloadFileResult result = new PNDownloadFileResult(); - result.FileBytes = outputBytes; - result.FileName = currentFileName; - callback.OnResponse(result, r.Result.Item2); - } - else - { - if (r.Result.Item2 != null) - { - callback.OnResponse(null, r.Result.Item2); - } - } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); - - - } - - private async Task> ProcessFileDownloadRequest(Dictionary externalQueryParam) - { - PNResult ret = new PNResult(); - - if (string.IsNullOrEmpty(this.currentFileId)) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing File Id", new ArgumentException("Missing File Id")) }; - ret.Status = errStatus; - return ret; - } - - if (string.IsNullOrEmpty(this.currentFileName)) - { - PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid file name", new ArgumentException("Invalid file name")) }; - ret.Status = errStatus; - return ret; - } - - var requestParameter = CreateRequestParameter(); - IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); - - Uri request = urlBuilder.BuildGetFileUrlOrDeleteReqest(Constants.GET, "", this.channelName, this.currentFileId, this.currentFileName, externalQueryParam, PNOperationType.PNDownloadFileOperation); - - RequestState requestState = new RequestState(); - requestState.ResponseType = PNOperationType.PNDownloadFileOperation; - requestState.Reconnect = false; - requestState.EndPointOperation = this; - - Tuple JsonAndStatusTuple = await UrlProcessRequestForStream(request, requestState, false,"").ConfigureAwait(false); - ret.Status = JsonAndStatusTuple.Item2; - byte[] item1Bytes = JsonAndStatusTuple.Item1; - if (item1Bytes != null) - { - byte[] outputBytes = null; - if (string.IsNullOrEmpty(this.currentFileCipherKey) && string.IsNullOrEmpty(config.CipherKey) && config.CryptoModule == null) - { - outputBytes = item1Bytes; - } - else - { - CryptoModule currentCryptoModule = !string.IsNullOrEmpty(this.currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(this.currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null)); - try - { - outputBytes = currentCryptoModule.Decrypt(item1Bytes); - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Stream length (after Decrypt)= {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), item1Bytes.Length), config.LogVerbosity); - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine("{0}\nMessage might be not encrypted, returning as is...", ex.ToString()); - outputBytes = item1Bytes; - ret.Status = new PNStatus { Error = true, ErrorData = new PNErrorData("Decryption error", ex) }; - } - } - - PNDownloadFileResult result = new PNDownloadFileResult(); - result.FileBytes = outputBytes; - result.FileName = currentFileName; - ret.Result = result; - } - - return ret; - } - - private RequestParameter CreateRequestParameter() - { + public class DownloadFileOperation : PubnubCoreBase + { + private readonly PNConfiguration config; + private readonly IJsonPluggableLibrary jsonLibrary; + private readonly IPubnubUnitTest unit; + private readonly IPubnubLog pubnubLog; + + private PNCallback savedCallback; + private Dictionary queryParam; + + private string channelName; + private string currentFileId; + private string currentFileName; + private string currentFileCipherKey; + + public DownloadFileOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, IPubnubLog log, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, log, tokenManager, instance) + { + config = pubnubConfig; + jsonLibrary = jsonPluggableLibrary; + unit = pubnubUnit; + pubnubLog = log; + } + + public DownloadFileOperation Channel(string channel) + { + this.channelName = channel; + return this; + } + + public DownloadFileOperation FileId(string fileId) + { + this.currentFileId = fileId; + return this; + } + + public DownloadFileOperation FileName(string fileName) + { + this.currentFileName = fileName; + return this; + } + + public DownloadFileOperation CipherKey(string cipherKeyForFile) + { + this.currentFileCipherKey = cipherKeyForFile; + return this; + } + + public DownloadFileOperation QueryParam(Dictionary customQueryParam) + { + this.queryParam = customQueryParam; + return this; + } + + public void Execute(PNCallback callback) + { + if (callback == null) { + throw new ArgumentException("Missing callback"); + } + + if (string.IsNullOrEmpty(this.currentFileId)) { + throw new ArgumentException("Missing File Id"); + } + if (string.IsNullOrEmpty(this.currentFileName)) { + throw new ArgumentException("Missing File Name"); + } + + ProcessFileDownloadRequest(this.queryParam, savedCallback); + } + + public async Task> ExecuteAsync() + { + return await ProcessFileDownloadRequest(this.queryParam).ConfigureAwait(false); + } + + internal void Retry() + { + ProcessFileDownloadRequest(this.queryParam, savedCallback); + } + + private void ProcessFileDownloadRequest(Dictionary externalQueryParam, PNCallback callback) + { + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNDownloadFileOperation; + requestState.PubnubCallback = callback; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + + byte[] fileContentBytes = null; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNDownloadFileOperation); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + fileContentBytes = transportResponse.Content; + if (fileContentBytes != null) { + byte[] outputBytes = null; + if (string.IsNullOrEmpty(this.currentFileCipherKey) && string.IsNullOrEmpty(config.CipherKey) && config.CryptoModule == null) { + outputBytes = fileContentBytes; + } else { + CryptoModule currentCryptoModule = !string.IsNullOrEmpty(this.currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(this.currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null)); + try { + outputBytes = currentCryptoModule.Decrypt(fileContentBytes); + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Stream length (after Decrypt)= {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), fileContentBytes.Length), config.LogVerbosity); + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine("{0}\nMessage might be not encrypted, returning as is...", ex.ToString()); + outputBytes = fileContentBytes; + } + } + PNDownloadFileResult result = new PNDownloadFileResult(); + result.FileBytes = outputBytes; + result.FileName = currentFileName; + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, 200, null); + callback.OnResponse(result, status); + } else { + PNStatus errorStatus = GetStatusIfError(requestState, null); + callback.OnResponse(default, errorStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNDownloadFileOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); + } + }); + } + private async Task> ProcessFileDownloadRequest(Dictionary externalQueryParam) + { + PNResult returnValue = new PNResult(); + + if (string.IsNullOrEmpty(this.currentFileId)) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Missing File Id", new ArgumentException("Missing File Id")) }; + returnValue.Status = errStatus; + return returnValue; + } + + if (string.IsNullOrEmpty(this.currentFileName)) { + PNStatus errStatus = new PNStatus { Error = true, ErrorData = new PNErrorData("Invalid file name", new ArgumentException("Invalid file name")) }; + returnValue.Status = errStatus; + return returnValue; + } + + + IUrlRequestBuilder urlBuilder = new UrlRequestBuilder(config, jsonLibrary, unit, pubnubLog, (PubnubInstance != null && !string.IsNullOrEmpty(PubnubInstance.InstanceId) && PubnubTokenMgrCollection.ContainsKey(PubnubInstance.InstanceId)) ? PubnubTokenMgrCollection[PubnubInstance.InstanceId] : null, (PubnubInstance != null) ? PubnubInstance.InstanceId : ""); + + Uri request = urlBuilder.BuildGetFileUrlOrDeleteReqest(Constants.GET, "", this.channelName, this.currentFileId, this.currentFileName, externalQueryParam, PNOperationType.PNDownloadFileOperation); + + RequestState requestState = new RequestState(); + requestState.ResponseType = PNOperationType.PNDownloadFileOperation; + requestState.Reconnect = false; + requestState.EndPointOperation = this; + var requestParameter = CreateRequestParameter(); + var transportRequest = PubnubInstance.transportMiddleware.PreapareTransportRequest(requestParameter: requestParameter, operationType: PNOperationType.PNDownloadFileOperation); + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest); + byte[] fileContentBytes = null; + if (transportResponse.Error == null) { + fileContentBytes = transportResponse.Content; + if (fileContentBytes != null) { + byte[] outputBytes = null; + if (string.IsNullOrEmpty(this.currentFileCipherKey) && string.IsNullOrEmpty(config.CipherKey) && config.CryptoModule == null) { + outputBytes = fileContentBytes; + } else { + CryptoModule currentCryptoModule = !string.IsNullOrEmpty(this.currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(this.currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null)); + try { + outputBytes = currentCryptoModule.Decrypt(fileContentBytes); + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0}, Stream length (after Decrypt)= {1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), fileContentBytes.Length), config.LogVerbosity); + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine("{0}\nFile content might be not encrypted, returning as is...", ex.ToString()); + outputBytes = fileContentBytes; + returnValue.Status = new PNStatus { Error = true, ErrorData = new PNErrorData("Decryption error", ex) }; + } + } + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, transportResponse.StatusCode, null); + PNDownloadFileResult result = new PNDownloadFileResult(); + result.FileBytes = outputBytes; + result.FileName = currentFileName; + returnValue.Result = result; + returnValue.Status = status; + } else { + PNStatus errorStatus = GetStatusIfError(requestState, null); + returnValue.Status = errorStatus; + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNDownloadFileOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + returnValue.Status = status; + } + return returnValue; + } + + private RequestParameter CreateRequestParameter() + { List pathSegments = new List { "v1", @@ -273,26 +213,21 @@ private RequestParameter CreateRequestParameter() Dictionary requestQueryStringParams = new Dictionary(); - if (queryParam != null && queryParam.Count > 0) - { - foreach (KeyValuePair kvp in queryParam) - { - if (!requestQueryStringParams.ContainsKey(kvp.Key)) - { - requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNDownloadFileOperation, false, false, false)); - } - } - } - - string queryString = UriUtil.BuildQueryString(requestQueryStringParams); - - var requestParameter = new RequestParameter() { - RequestType = Constants.GET, - PathSegment = pathSegments, - Query = requestQueryStringParams - }; + if (queryParam != null && queryParam.Count > 0) { + foreach (KeyValuePair kvp in queryParam) { + if (!requestQueryStringParams.ContainsKey(kvp.Key)) { + requestQueryStringParams.Add(kvp.Key, UriUtil.EncodeUriComponent(kvp.Value.ToString(), PNOperationType.PNDownloadFileOperation, false, false, false)); + } + } + } + + var requestParameter = new RequestParameter() { + RequestType = Constants.GET, + PathSegment = pathSegments, + Query = requestQueryStringParams + }; - return requestParameter; - } - } + return requestParameter; + } + } } diff --git a/src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs b/src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs index b5f8d7c69..84e6f13a8 100644 --- a/src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs +++ b/src/Api/PubnubApi/EndPoint/Files/SendFileOperation.cs @@ -2,14 +2,8 @@ using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; -using System.Net; using System.Text; -using System.Threading; using System.Threading.Tasks; -#if !NET35 && !NET40 -using System.Collections.Concurrent; -#endif using PubnubApi.Security.Crypto; using PubnubApi.Security.Crypto.Cryptors; @@ -27,7 +21,7 @@ public class SendFileOperation : PubnubCoreBase private string channelName; private object publishFileMessageContent; private string sendFileFullPath; - private string sendFileName = ""; + private string sendFileName = string.Empty; private byte[] sendFileBytes = null; private string currentFileCipherKey; private string currentFileId; @@ -76,15 +70,11 @@ public SendFileOperation Ttl(int ttl) public SendFileOperation File(string fileNameWithFullPath) { this.sendFileFullPath = fileNameWithFullPath; -#if !NETSTANDARD10 && !NETSTANDARD11 - // manually set filename should take precedence + if (System.IO.File.Exists(fileNameWithFullPath) && string.IsNullOrEmpty(sendFileName)) { - sendFileName = System.IO.Path.GetFileName(fileNameWithFullPath); + sendFileName = Path.GetFileName(fileNameWithFullPath); } return this; -#else - throw new NotSupportedException("FileSystem not supported in NetStandard 1.0/1.1. Consider higher version of .NetStandard."); -#endif } public SendFileOperation File(byte[] byteArray) @@ -128,17 +118,7 @@ public void Execute(PNCallback callback) if (string.IsNullOrEmpty(this.sendFileName)) { throw new ArgumentException("Missing File"); } - -#if NETFX_CORE || WINDOWS_UWP || UAP || NETSTANDARD10 || NETSTANDARD11 || NETSTANDARD12 - Task.Factory.StartNew(() => - { - ProcessFileUpload(this.queryParam, callback); - }, CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default).ConfigureAwait(false); -#else - new Thread(() => { - ProcessFileUpload(this.queryParam, callback); - }) { IsBackground = true }.Start(); -#endif + ProcessFileUpload(this.queryParam, callback); } public async Task> ExecuteAsync() @@ -148,7 +128,6 @@ public async Task> ExecuteAsync() private void ProcessFileUpload(Dictionary externalQueryParam, PNCallback callback) { - // File Upload URL PNResult generateFileUploadUrl = GenerateFileUploadUrl(externalQueryParam).Result; PNGenerateFileUploadUrlResult generateFileUploadUrlResult = generateFileUploadUrl.Result; PNStatus generateFileUploadUrlStatus = generateFileUploadUrl.Status; @@ -160,7 +139,6 @@ private void ProcessFileUpload(Dictionary externalQueryParam, PN } return; } - // Got File Upload URL LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); RequestState requestState = new RequestState(); requestState.ResponseType = PNOperationType.PNFileUploadOperation; @@ -168,74 +146,69 @@ private void ProcessFileUpload(Dictionary externalQueryParam, PN requestState.Reconnect = false; requestState.EndPointOperation = this; requestState.UsePostMethod = true; - - - // byteArray Content preparation. byte[] sendFileByteArray = sendFileBytes ?? GetByteArrayFromFilePath(sendFileFullPath); - - - string dataBoundary = String.Format(CultureInfo.InvariantCulture, "----------{0:N}", Guid.NewGuid()); + string dataBoundary = string.Format(CultureInfo.InvariantCulture, "----------{0:N}", Guid.NewGuid()); string contentType = "multipart/form-data; boundary=" + dataBoundary; CryptoModule currentCryptoModule = null; if (!string.IsNullOrEmpty(this.currentFileCipherKey) || !string.IsNullOrEmpty(config.CipherKey) || config.CryptoModule != null) { currentCryptoModule = !string.IsNullOrEmpty(this.currentFileCipherKey) ? new CryptoModule(new LegacyCryptor(this.currentFileCipherKey, true, pubnubLog), null) : (config.CryptoModule ??= new CryptoModule(new LegacyCryptor(config.CipherKey, true, pubnubLog), null)); } byte[] postData = GetMultipartFormData(sendFileByteArray, generateFileUploadUrlResult.FileName, generateFileUploadUrlResult.FileUploadRequest.FormFields, dataBoundary, currentCryptoModule, config, pubnubLog); - - // Content , Url is availale - string json; - UrlProcessRequest(new Uri(generateFileUploadUrlResult.FileUploadRequest.Url), requestState, false, postData, contentType).ContinueWith(r => { - json = r.Result.Item1; - if (!string.IsNullOrEmpty(json) && string.Equals(json, "{}", StringComparison.OrdinalIgnoreCase)) { - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl -> file upload OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - //do internal publish after successful file upload - - Dictionary publishPayload = new Dictionary(); - if (this.publishFileMessageContent != null && !string.IsNullOrEmpty(this.publishFileMessageContent.ToString())) { - publishPayload.Add("message", this.publishFileMessageContent); - } - publishPayload.Add("file", new Dictionary { + var transportRequest = new TransportRequest() { + RequestType = Constants.POST, + RequestUrl = generateFileUploadUrlResult.FileUploadRequest.Url, + BodyContentBytes = postData, + }; + transportRequest.Headers.Add("Content-Type", contentType); + PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest).ContinueWith(t => { + var transportResponse = t.Result; + if (transportResponse.Error == null) { + if (transportResponse.StatusCode == 204 && transportResponse.Error == null) { + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl -> file upload OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); + Dictionary publishPayload = new Dictionary(); + if (this.publishFileMessageContent != null && !string.IsNullOrEmpty(this.publishFileMessageContent.ToString())) { + publishPayload.Add("message", this.publishFileMessageContent); + } + currentFileId = generateFileUploadUrlResult.FileId; + sendFileName = generateFileUploadUrlResult.FileName; + publishPayload.Add("file", new Dictionary { { "id", generateFileUploadUrlResult.FileId }, { "name", generateFileUploadUrlResult.FileName } }); - - int publishFileRetryLimit = config.FileMessagePublishRetryLimit; - int currentFileRetryCount = 0; - bool publishFailed = false; - do { - currentFileRetryCount += 1; - PNResult publishFileMessageResponse = PublishFileMessage(publishPayload, queryParam).Result; - PNPublishFileMessageResult publishFileMessage = publishFileMessageResponse.Result; - PNStatus publishFileMessageStatus = publishFileMessageResponse.Status; - if (publishFileMessageStatus != null && !publishFileMessageStatus.Error && publishFileMessage != null) { - publishFailed = false; - PNFileUploadResult result = new PNFileUploadResult(); - result.Timetoken = publishFileMessage.Timetoken; - result.FileId = generateFileUploadUrlResult.FileId; - result.FileName = generateFileUploadUrlResult.FileName; - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl -> file upload -> PublishFileMessage -> OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); - r.Result.Item2.Error = false; - callback.OnResponse(result, r.Result.Item2); - } else { - publishFailed = true; - if (currentFileRetryCount == publishFileRetryLimit) { - callback.OnResponse(null, publishFileMessageStatus); + int publishFileRetryLimit = config.FileMessagePublishRetryLimit; + int currentFileRetryCount = 0; + bool publishFailed = false; + do { + currentFileRetryCount += 1; + PNResult publishFileMessageResponse = PublishFileMessage(publishPayload, queryParam).Result; + PNPublishFileMessageResult publishFileMessage = publishFileMessageResponse.Result; + PNStatus publishFileMessageStatus = publishFileMessageResponse.Status; + if (publishFileMessageStatus != null && !publishFileMessageStatus.Error && publishFileMessage != null) { + publishFailed = false; + PNFileUploadResult result = new PNFileUploadResult(); + result.Timetoken = publishFileMessage.Timetoken; + result.FileId = generateFileUploadUrlResult.FileId; + result.FileName = generateFileUploadUrlResult.FileName; + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl -> file upload -> PublishFileMessage -> OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); + var status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, 200, null); + callback.OnResponse(result, status); + } else { + publishFailed = true; + if (currentFileRetryCount == publishFileRetryLimit) { + callback.OnResponse(null, publishFileMessageStatus); + } + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} PublishFileMessage Failed. currentFileRetryCount={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), currentFileRetryCount), config.LogVerbosity); + Task.Delay(1000).Wait(); } - LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} PublishFileMessage Failed. currentFileRetryCount={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), currentFileRetryCount), config.LogVerbosity); -#if !NET35 && !NET40 - Task.Delay(1000).Wait(); -#else - Thread.Sleep(1000); -#endif } - } - while (publishFailed && currentFileRetryCount <= publishFileRetryLimit); - } // There is error in uploading file content. - else { - if (r.Result.Item2 != null) { - callback.OnResponse(null, r.Result.Item2); + while (publishFailed && currentFileRetryCount <= publishFileRetryLimit); + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNFileUploadOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + requestState.PubnubCallback.OnResponse(default, status); } } - }, TaskContinuationOptions.ExecuteSynchronously).Wait(); + }); } private async Task> ProcessFileUpload(Dictionary externalQueryParam) @@ -247,8 +220,6 @@ private async Task> ProcessFileUpload(Dictionary generateFileUploadUrl = await GenerateFileUploadUrl(externalQueryParam).ConfigureAwait(false); PNGenerateFileUploadUrlResult generateFileUploadUrlResult = generateFileUploadUrl.Result; PNStatus generateFileUploadUrlStatus = generateFileUploadUrl.Status; @@ -268,18 +239,37 @@ private async Task> ProcessFileUpload(Dictionary JsonAndStatusTuple = await UrlProcessRequest(new Uri(generateFileUploadUrlResult.FileUploadRequest.Url), requestState, false, postData, contentType).ConfigureAwait(false); + var transportRequest = new TransportRequest() { + RequestType = Constants.POST, + RequestUrl = generateFileUploadUrlResult.FileUploadRequest.Url, + BodyContentBytes = postData, + }; + transportRequest.Headers.Add("Content-Type", contentType); + Tuple JsonAndStatusTuple; + string responseString; + var transportResponse = await PubnubInstance.transportMiddleware.Send(transportRequest: transportRequest); + if (transportResponse.StatusCode == 204 && transportResponse.Error == null) { + responseString = "{}"; + PNStatus errStatus = GetStatusIfError(requestState, responseString); + if (errStatus == null) { + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(requestState.ResponseType, PNStatusCategory.PNAcknowledgmentCategory, requestState, 200, null); + JsonAndStatusTuple = new Tuple(responseString, status); + } else { + JsonAndStatusTuple = new Tuple(string.Empty, errStatus); + } + } else { + int statusCode = PNStatusCodeHelper.GetHttpStatusCode(transportResponse.Error.Message); + PNStatusCategory category = PNStatusCategoryHelper.GetPNStatusCategory(statusCode, transportResponse.Error.Message); + PNStatus status = new StatusBuilder(config, jsonLibrary).CreateStatusResponse(PNOperationType.PNFileUploadOperation, category, requestState, statusCode, new PNException(transportResponse.Error.Message, transportResponse.Error)); + JsonAndStatusTuple = new Tuple(string.Empty, status); + } returnValue.Status = JsonAndStatusTuple.Item2; string json = JsonAndStatusTuple.Item1; if (!string.IsNullOrEmpty(json)) { @@ -290,13 +280,14 @@ private async Task> ProcessFileUpload(Dictionary { { "id", generateFileUploadUrlResult.FileId }, { "name", generateFileUploadUrlResult.FileName } }); int publishFileRetryLimit = config.FileMessagePublishRetryLimit; int currentFileRetryCount = 0; - bool publishFailed = false; + bool publishFailed; do { currentFileRetryCount += 1; PNResult publishFileMessageResponse = await PublishFileMessage(publishPayload, queryParam).ConfigureAwait(false); @@ -310,16 +301,12 @@ private async Task> ProcessFileUpload(Dictionary file upload -> PublishFileMessage -> OK.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); //do internal publish after successful file upload + LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} GenerateFileUploadUrl -> file upload -> PublishFileMessage -> Success.", DateTime.Now.ToString(CultureInfo.InvariantCulture)), config.LogVerbosity); //do internal publish after successful file upload } else { publishFailed = true; returnValue.Status = publishFileMessageStatus; LoggingMethod.WriteToLog(pubnubLog, string.Format(CultureInfo.InvariantCulture, "DateTime {0} PublishFileMessage Failed. currentFileRetryCount={1}", DateTime.Now.ToString(CultureInfo.InvariantCulture), currentFileRetryCount), config.LogVerbosity); -#if !NET35 && !NET40 Task.Delay(1000).Wait(); -#else - Thread.Sleep(1000); -#endif } } while (publishFailed && currentFileRetryCount <= publishFileRetryLimit); @@ -336,8 +323,6 @@ private async Task> GenerateFileUploadUr returnValue.Status = errStatus; return returnValue; } - - RequestState requestState = new RequestState(); requestState.ResponseType = PNOperationType.PNGenerateFileUploadUrlOperation; requestState.Reconnect = false; @@ -430,23 +415,18 @@ private async Task> PublishFileMessage(obje private static byte[] GetByteArrayFromFilePath(string filePath) { -#if !NETSTANDARD10 && !NETSTANDARD11 byte[] byteArray = null; if (!string.IsNullOrEmpty(filePath)) { byteArray = System.IO.File.ReadAllBytes(filePath); } return byteArray; -#else - throw new NotSupportedException("FileSystem not supported in NetStandard 1.0/1.1. Consider higher version of .NetStandard."); -#endif - } private static byte[] GetMultipartFormData(byte[] sendFileByteArray, string fileName, Dictionary formFields, string dataBoundary, CryptoModule currentCryptoModule, PNConfiguration config, IPubnubLog pubnubLog) { byte[] ret = null; string fileContentType = "application/octet-stream"; - using (Stream dataStream = new System.IO.MemoryStream()) { + using (Stream dataStream = new MemoryStream()) { foreach (var kvp in formFields) { if (kvp.Key == "Content-Type" && kvp.Value != null && !string.IsNullOrEmpty(kvp.Value.ToString())) { fileContentType = kvp.Value.ToString(); @@ -489,9 +469,6 @@ private static byte[] GetMultipartFormData(byte[] sendFileByteArray, string file ret = new byte[dataStream.Length]; int bytesRead = dataStream.Read(ret, 0, ret.Length); System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "MultipartFormData byte count = {0}", bytesRead)); -#if NET35 || NET40 || NET45 || NET461 || NET48 - dataStream.Close(); -#endif } return ret; }