/// <summary> /// This method will send data to the API for storage in the database /// </summary> /// <param name="productList">List of products with their image url</param> /// <returns></returns> private async Task <bool> SendDataToAPI(List <Products> productList) { try { var serverDetails = new SettingsService().LoadSettings(); var productData = new ProductData { Username = serverDetails.Username, Password = serverDetails.Password, Products = productList }; var data = JsonConvert.SerializeObject(productData); var result = await HttpService.PostModelLinks(productData, serverDetails.ServerURL); if (result.Status.ToLowerInvariant().Equals("success")) { return(true); } else { ProcessingException?.Invoke("Could not save data to Server due to following reason. Reason:" + result.Message); return(false); } } catch (Exception ex) { ProcessingException?.Invoke("There was an error while sending the data to the server. Exception: " + ex.Message); return(false); } }
private async Task ProcessQueueAsync( ChannelReader <TrackInfo> queueReader, CancellationToken cancellationToken = default) { while (await queueReader.WaitToReadAsync(cancellationToken) .ConfigureAwait(false)) { var info = await queueReader.ReadAsync(cancellationToken); _logger.LogInformation("Playing {title} ({url})", info.TrackName, info.OriginalLocation); CurrentTrack = info; try { await ProcessQueueItemAsync(info, cancellationToken); } catch (OperationCanceledException) when(!cancellationToken.IsCancellationRequested) { /* expected for unsupported tracks */ } catch (Exception e) { if (!(e is AggregateException aggregate)) { aggregate = new AggregateException(e); } var args = new UnobservedTaskExceptionEventArgs(aggregate); ProcessingException?.Invoke(this, args); if (!args.Observed) { _logger.LogError(aggregate, "Unhandled exception occured while processing " + "queue. Track {url} may be skipped.", info.OriginalLocation); } } } }
/// <summary> /// This method will store the data locally in the JSON file at the destination location /// </summary> /// <param name="productList">List of products</param> /// <param name="destinationLocation">Destination location path</param> private bool StoreDataLocally(List <Products> productList, string destinationLocation) { try { // Combine all the processed textfile in 1 Json file and place in the destiantion folder var destinationFile = Path.Combine(destinationLocation, "ParameterizedData.json"); using (StreamWriter file = File.CreateText(destinationFile)) { JsonSerializer serializer = new JsonSerializer(); serializer.Serialize(file, productList); } return(true); } catch (Exception ex) { ProcessingException?.Invoke("There was an error while storing the data at local destination. Exception: " + ex.Message); return(false); } }
/// <summary> /// Method to start converting the ifc files in to the GLTF format /// </summary> /// <param name="sourceLocation">Source location path</param> /// <param name="destinationLocation">Destination location path</param> /// <param name="destinationType">Type of destination, such as server, local or both</param> /// <returns>IFC convert Status to update the UI</returns> public async Task <IFCConvertStatus> ConvertFiles(string sourceLocation, string destinationLocation, DestinationLocationType destinationType) { try { return(await Task.Run(async() => { // Check if destination folder exist if (!Directory.Exists(destinationLocation)) { ProcessingException?.Invoke("The destination folder does not exist. Please specify the correct folder"); return IFCConvertStatus.Error; } // get all file names from the source location var allFilenames = Directory.EnumerateFiles(sourceLocation).Select(p => Path.GetFileName(p)); // Get all filenames that have a .ifc extension var files = allFilenames.Where(fn => Path.GetExtension(fn) == ".ifc"); // If there are no files, then return to notify the user if (files == null || files.Count() == 0) { return IFCConvertStatus.NoFiles; } // Get total number of files, (need it for the progress bar) var totalFiles = files.Count(); // Send the total count of the files to the viewmodel for update on UI TotalFiles?.Invoke(totalFiles.ToString()); // Process each file and convert it foreach (var file in files) { var sourceFile = Path.Combine(sourceLocation, file); var filePathWithGLTFExtentsion = Path.ChangeExtension(file, ".glb"); var destinationFile = Path.Combine(destinationLocation, filePathWithGLTFExtentsion); IFCConvert.Convert(sourceFile, destinationFile); totalFiles--; // Send message to UI to update progress bar RemainingFiles?.Invoke((totalFiles).ToString()); } // Send a call to the S3 bucket to upload data and the API if (destinationType == DestinationLocationType.Both) { var productList = UploadModels(files, sourceLocation, destinationLocation); if (productList != null) { var result = await SendDataToAPI(productList); if (!result) { return IFCConvertStatus.Error; } } else { return IFCConvertStatus.Error; } } // Return success message return IFCConvertStatus.Done; })); } catch (Exception ex) { ProcessingException?.Invoke("There was an error while converting the IFC files. Exception: " + ex.Message); return(IFCConvertStatus.Error); } }
/// <summary> /// This method will utilize the S3UploadService to upload the converted models to the S3 bucket. /// </summary> /// <param name="files">List of files that need to be uploaded</param> /// <param name="sourceLocation"></param> /// <param name="destinationLocation"></param> /// <returns>Return list of products or null</returns> private List <Products> UploadModels(IEnumerable <string> files, string sourceLocation, string destinationLocation) { try { // Get the AWS details from the settings var awsDetails = new SettingsService().LoadSettings(); // Initialization var uploader = new S3UploadService(awsDetails.BucketName, awsDetails.AccessKey, awsDetails.SecretKey); var sourceFiles = new List <string>(); var productUrls = new List <Products>(); // Create 3dModel Folder on AWS to upload the models uploader.CreateFolder(); // Get the List of all 3D Models foreach (var file in files) { var sourceFile = Path.Combine(sourceLocation, file); var filePathWithGLTFExtentsion = Path.ChangeExtension(file, ".glb"); var sourceFilePath = Path.Combine(destinationLocation, filePathWithGLTFExtentsion); sourceFiles.Add(sourceFilePath); } // Model Count for Progress bar var totalModels = files.Count(); var uploaded = 0; // Create separate threads to upload files on the AWS. Parallel.ForEach(sourceFiles, currentFile => { // Call a method to see if the file is created at the location or not before accessing it. var fileFound = WaitForFile(currentFile); string filename = Path.GetFileName(currentFile); // If file is found, then start uploading process // else send a message to the user with the issue related to filename. if (fileFound) { var product = new Products { Code = Path.GetFileNameWithoutExtension(currentFile), ModelURL = uploader.UploadFile(currentFile, filename), ProductParameters = null }; productUrls.Add(product); uploaded++; RemainingModels?.Invoke((totalModels - uploaded).ToString()); } else { ProcessingException?.Invoke("The file: " + filename + " could not be found in the destination folder for uploading"); } }); // Return list of all the urls for the uploaded objects return(productUrls); } catch (Exception ex) { ProcessingException?.Invoke("There was an exeception while uploading the files to S3 bucket. Exception: " + ex.Message); return(null); } }
/// <summary> /// Method to process the text file and generate JSON files /// </summary> /// <param name="sourceLocation">Source location path</param> /// <param name="destinationLocation">Destination location path</param> /// <returns>Textfile processing Status to update the UI</returns> public async Task <TextfileProcessingStatus> ProcessFiles(string sourceLocation, string destinationLocation, DestinationLocationType destinationType) { try { return(await Task.Run(async() => { // get all file names from the source location var allFilenames = Directory.EnumerateFiles(sourceLocation).Select(p => Path.GetFileName(p)); // Get all filenames that have a .txt extension var files = allFilenames.Where(fn => Path.GetExtension(fn) == ".txt"); // If there are no files, then return to notify the user if (files == null || files.Count() == 0) { return TextfileProcessingStatus.NoFiles; } // Get total number of files, (need it for the progress bar) var totalFiles = files.Count(); // Send the total count of the files to the viewmodel for update on UI TotalFiles?.Invoke(totalFiles.ToString()); // List for all the products with their key value pairs of data. This list will be serialzied and sent to the API var productList = new List <Products>(); // Process each file and convert it foreach (var file in files) { // Get the path for the source file var sourceFile = Path.Combine(sourceLocation, file); // Read all the lines of the file var lines = File.ReadAllLines(sourceFile).ToArray(); // Final Heading Tokens after being cleaned and formatted would be stored in this list var finalHeadings = ProcessHeaderString(lines[0]); // Loop over rest of the lines apart from the heading line foreach (var line in lines.Skip(1)) { // Will contain the values from the CSV file var content = ProcessData(line); // Time to process the strings and convert to Json // However, if this condition is not satisfied, that means there is something wrong with the file. We need to alert the user. if (content != null && finalHeadings != null && content.Count() > 0 && finalHeadings.Count > 0 && finalHeadings.Count == content.Count) { var product = new Products { ProductParameters = new List <ProductParameters>(), }; // Now make the key value pairs of the tokenized strings for (var i = 0; i < finalHeadings.Count; i++) { // add a check to fill out the product code if the token is "Product Code". Then we need to update the product code // otherwise, fill out key value pairs if (finalHeadings[i].ToLowerInvariant().Equals("product code")) { product.Code = content[i]; } else { var productParam = new ProductParameters { Key = finalHeadings[i], Value = content[i] }; product.ProductParameters.Add(productParam); } } productList.Add(product); } else { ColumnMismatch?.Invoke("A mismatch between heading and content columns occured in file: " + Path.GetFileNameWithoutExtension(file)); } } totalFiles--; // Send message to UI to update progress bar RemainingFiles?.Invoke((totalFiles).ToString()); } // check user's preference and save or send the file accordingly. if (destinationType == DestinationLocationType.Local) { var result = StoreDataLocally(productList, destinationLocation); return result ? TextfileProcessingStatus.Done : TextfileProcessingStatus.Error; } else if (destinationType == DestinationLocationType.Server) { var result = await SendDataToAPI(productList); return result ? TextfileProcessingStatus.Done : TextfileProcessingStatus.Error; } else if (destinationType == DestinationLocationType.Both) { var localStorageResult = StoreDataLocally(productList, destinationLocation); var serverStorageResult = await SendDataToAPI(productList); return (localStorageResult && serverStorageResult) ? TextfileProcessingStatus.Done : TextfileProcessingStatus.PartialSuccess; } // Return success message return TextfileProcessingStatus.Done; })); } catch (Exception ex) { ProcessingException?.Invoke("There was an error while processing the textfiles. Exception: " + ex.Message); return(TextfileProcessingStatus.Error); } }