RegexReplaceApiController.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. using LAPS_XMLQC_Service.Models;
  2. using LAPS_XMLQC_Service.Services;
  3. using Microsoft.AspNetCore.Mvc;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Threading.Tasks;
  8. using System.Threading;
  9. using System.IO;
  10. using Microsoft.AspNetCore.Authorization;
  11. namespace LAPS_XMLQC_Service.Controllers.RegexReplace
  12. {
  13. [Route("api/[controller]")]
  14. [ApiController]
  15. public class RegexReplaceApiController : ControllerBase
  16. {
  17. private readonly RegexPatternService _regexPatternService;
  18. private readonly FileSearchService _fileSearchService;
  19. public RegexReplaceApiController(RegexPatternService regexPatternService, FileSearchService fileSearchService)
  20. {
  21. _regexPatternService = regexPatternService;
  22. _fileSearchService = fileSearchService;
  23. }
  24. [Authorize]
  25. [HttpGet("GetPatterns")]
  26. public IActionResult GetPatterns()
  27. {
  28. var patterns = _regexPatternService.GetRegexPatterns();
  29. return Ok(patterns);
  30. }
  31. [Authorize]
  32. [HttpPost("Search")]
  33. public async Task<IActionResult> PerformSearch([FromBody] SearchRequest request)
  34. {
  35. var results = await _fileSearchService.SearchFiles(request.DirectoryPath, request.SearchTerm, request.FileType, request.CaseInsensitive, request.SingleLine, request.MultiLine, request.IgnoreWhitespace, request.ExplicitCapture);
  36. return Ok(results);
  37. }
  38. [Authorize]
  39. [HttpPost("Preview")]
  40. public async Task<IActionResult> PreviewChanges([FromBody] SearchRequest request)
  41. {
  42. var results = await _fileSearchService.PreviewOrReplaceAll(request.DirectoryPath, request.SearchTerm, request.ReplacementText, request.FileType, request.CaseInsensitive, request.SingleLine, request.MultiLine, request.IgnoreWhitespace, request.ExplicitCapture, "Preview");
  43. return Ok(results);
  44. }
  45. [Authorize]
  46. [HttpPost("ReplaceAll")]
  47. public async Task<IActionResult> ReplaceAllChanges([FromBody] SearchRequest request)
  48. {
  49. var results = await _fileSearchService.PreviewOrReplaceAll(request.DirectoryPath, request.SearchTerm, request.ReplacementText, request.FileType, request.CaseInsensitive, request.SingleLine, request.MultiLine, request.IgnoreWhitespace, request.ExplicitCapture, "ReplaceAll");
  50. return Ok(results);
  51. }
  52. [Authorize]
  53. [HttpPost("Apply")]
  54. public async Task<IActionResult> ApplyChanges([FromBody] MatchedResult results)
  55. {
  56. if (results == null)
  57. {
  58. return BadRequest("No changes provided to apply.");
  59. }
  60. try
  61. {
  62. results = await _fileSearchService.ApplyChange(results);
  63. return Ok(results);
  64. }
  65. catch (Exception ex)
  66. {
  67. return StatusCode(500, $"An error occurred while applying changes: {ex.Message}");
  68. }
  69. }
  70. [Authorize]
  71. [HttpPost("Accept")]
  72. public IActionResult Accept([FromBody] List<MatchedResult> results)
  73. {
  74. if (results == null)
  75. {
  76. return BadRequest("No changes provided to apply.");
  77. }
  78. try
  79. {
  80. results = _fileSearchService.Accept(results);
  81. return Ok(results);
  82. }
  83. catch (Exception ex)
  84. {
  85. return StatusCode(500, $"An error occurred while applying changes: {ex.Message}");
  86. }
  87. }
  88. [Authorize]
  89. [HttpPost("Reject")]
  90. public IActionResult Reject([FromBody] List<MatchedResult> results)
  91. {
  92. if (results == null)
  93. {
  94. return BadRequest("No changes provided to apply.");
  95. }
  96. try
  97. {
  98. results = _fileSearchService.Reject(results);
  99. return Ok(results);
  100. }
  101. catch (Exception ex)
  102. {
  103. return StatusCode(500, $"An error occurred while applying changes: {ex.Message}");
  104. }
  105. }
  106. [Authorize]
  107. [HttpPost("Upload")]
  108. public async Task<IActionResult> UploadFiles([FromForm] UploadRequest request)
  109. {
  110. var results = new List<MatchedResult>();
  111. if (request?.Files == null || request.Files.Count == 0)
  112. {
  113. return BadRequest("No files were uploaded.");
  114. }
  115. string fileExtension = request.FileType.Replace("*", string.Empty);
  116. if (string.IsNullOrWhiteSpace(fileExtension))
  117. {
  118. return BadRequest("Invalid file type specified.");
  119. }
  120. // Limit the number of concurrent tasks
  121. int maxDegreeOfParallelism = 5; // Adjust this value based on your server's capabilities
  122. var semaphore = new SemaphoreSlim(maxDegreeOfParallelism);
  123. var tasks = request.Files.Select(async file =>
  124. {
  125. await semaphore.WaitAsync(); // Limit concurrent execution
  126. try
  127. {
  128. // Check if the file's extension matches the requested file type
  129. if (!Path.GetExtension(file.FileName).Equals(fileExtension, StringComparison.OrdinalIgnoreCase))
  130. {
  131. return null; // Skip files that don't match the extension
  132. }
  133. using var stream = new MemoryStream();
  134. await file.CopyToAsync(stream);
  135. var content = System.Text.Encoding.UTF8.GetString(stream.ToArray());
  136. // Perform regex search on the file content
  137. var matches = await _fileSearchService.SearchContent(content, request.SearchTerm,
  138. request.CaseInsensitive, request.SingleLine,
  139. request.MultiLine, request.IgnoreWhitespace, request.ExplicitCapture);
  140. // Calculate the total result count across all pattern results
  141. int resultCount = matches.Sum(patternResult => patternResult.Matches!.Count);
  142. return new MatchedResult
  143. {
  144. FileName = file.FileName,
  145. Content = content,
  146. PatternResults = matches,
  147. ResultCount = resultCount
  148. };
  149. }
  150. catch
  151. {
  152. // Log the error (or handle it as needed)
  153. // Return null to indicate an error for this file
  154. return null;
  155. }
  156. finally
  157. {
  158. semaphore.Release(); // Release the semaphore for the next task
  159. }
  160. });
  161. // Await all the tasks and filter out any null results
  162. var taskResults = await Task.WhenAll(tasks);
  163. results = taskResults.Where(result => result != null).Cast<MatchedResult>().ToList();
  164. return Ok(results);
  165. }
  166. }
  167. }