using CliWrap; using CliWrap.Buffered; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Net.Http; using System.Text; using System.Text.Json.Serialization; using static System.Net.Mime.MediaTypeNames; using Newtonsoft.Json; using BLV_API; namespace FaceValidator.Controllers { [Route("api/[controller]/[action]")] [ApiController] public class FaceFeatureController : ControllerBase { private readonly IWebHostEnvironment _hostingEnvironment; private readonly ILogger _logger; public FaceFeatureController( IWebHostEnvironment hostingEnvironment, ILogger logger) { _hostingEnvironment = hostingEnvironment; _logger = logger; } /// /// 提交人脸Url/File /// /// /// [HttpPost] public async Task ValidateFaceVal([FromForm] UploadFileModel data) { try { var file = data.File; var faceUrl = data.FaceUrl; // 检查输入是否有效 if (file == null && string.IsNullOrWhiteSpace(faceUrl)) { return BadRequest("必须提供图片文件或图片URL"); } // 保存图片到本地临时文件 string tempImagePath; if (file != null) { // tempImagePath = await SaveUploadedFileAsync(file); } else { tempImagePath = await DownloadImageAsync(faceUrl); } // 调用验证方法 var validationResult = await FaceValidator(tempImagePath); // 清理临时文件 //System.IO.File.Delete(tempImagePath); return validationResult; } catch (Exception ex) { _logger.LogError(ex, "人脸验证过程中发生未处理异常"); return StatusCode(500, $"系统错误: {ex.Message}"); } } private async Task SaveUploadedFileAsync(IFormFile file) { var tempFileName = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}"; var tempFilePath = Path.Combine(_hostingEnvironment.ContentRootPath, "wwwroot/upload", tempFileName); // 确保目录存在 Directory.CreateDirectory(Path.GetDirectoryName(tempFilePath)); using (var stream = new FileStream(tempFilePath, FileMode.Create)) { await file.CopyToAsync(stream); } return tempFilePath; } private async Task DownloadImageAsync(string faceUrl) { if (!Uri.TryCreate(faceUrl, UriKind.Absolute, out var uri)) { throw new ArgumentException("提供的图片URL无效"); } HttpClient httpClient = new(); var response = await httpClient.GetAsync(uri); if (!response.IsSuccessStatusCode) { throw new ApplicationException($"无法下载图片: {response.StatusCode}"); } var tempFileName = $"{Guid.NewGuid()}.jpg"; var tempFilePath = Path.Combine(_hostingEnvironment.ContentRootPath, "wwwroot/upload", tempFileName); // 确保目录存在 Directory.CreateDirectory(Path.GetDirectoryName(tempFilePath)); await using (var fs = new FileStream(tempFilePath, FileMode.Create)) await using (var stream = await response.Content.ReadAsStreamAsync()) { await stream.CopyToAsync(fs); } return tempFilePath; } [HttpPost] public async Task FaceValidator(string localImagePath) { // 1. 错误处理:确保参数不为空 if (string.IsNullOrWhiteSpace(localImagePath)) { return BadRequest("脸部数据参数不能为空"); } // 2. 确保图片文件存在 if (!System.IO.File.Exists(localImagePath)) { return BadRequest($"本地图片文件不存在: {localImagePath}"); } // 3. 使用绝对路径确保可靠性 var exePath = Path.Combine(_hostingEnvironment.ContentRootPath, "ValRel", "faceidtest.exe"); var exeDirectory = Path.GetDirectoryName(exePath); // 4. 检查可执行文件是否存在 if (!System.IO.File.Exists(exePath)) { _logger.LogError($"可执行文件不存在: {exePath}"); return StatusCode(500, $"人脸验证程序未找到"); } try { var stdOutBuffer = new StringBuilder(); var stdErrBuffer = new StringBuilder(); // 传递文件路径作为参数 var arguments = $"{localImagePath} 80x v3"; _logger.LogInformation($"执行人脸验证: {exePath} {arguments}"); // 创建取消令牌源并设置超时(例如20秒) using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(20)); var result = await Cli.Wrap(exePath) // 指定可执行文件 .WithArguments(arguments) // 传递参数 .WithWorkingDirectory(exeDirectory) // 在exe所在目录执行 .WithValidation(CommandResultValidation.None) // 退出条件 .WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdOutBuffer)) // 打印结果日志 .WithStandardErrorPipe(PipeTarget.ToStringBuilder(stdErrBuffer)) // 打印过程日志 .ExecuteAsync(cts.Token); // 设置取消令牌 var fullOutput = stdErrBuffer.ToString(); fullOutput += stdOutBuffer.ToString(); string[] lines = fullOutput.Split(["\r\n", "\r", "\n"], StringSplitOptions.None); var validationResult = ""; _logger.LogInformation($"结果: {fullOutput}"); var name = ""; foreach (var item in lines) { if (item.IndexOf("quality:") > -1) { validationResult = item.Split(":")[2].Trim(); break; } } var vurl = "http://blv-rd.tech:19099/upload/"; //var vurl = "http://piccheck.blv-oa.com/upload/"; //D:\\AFace\\wwwroot/upload\\d7d5f295-8c75-4308-b36a-367c650a8ac4.jpg vurl += Path.GetFileName(localImagePath); LogHelper.WriteLog("图片名称:" + Path.GetFileName(localImagePath) + $" 验证结果: {validationResult}"); if (double.TryParse(validationResult, out double validationResultNum)) { return Ok(new { Success = true, Result = result, ExitCode = 200, quality = validationResultNum, Url = vurl, }); } else { return Ok(new { Success = false, Result = result, ExitCode = 200, Msg = "验证错误", Url = vurl, }); } } catch (OperationCanceledException) { _logger.LogError("操作超时,人脸验证未完成"); return StatusCode(504, "验证超时"); } catch (Exception ex) { _logger.LogError(ex, "人脸验证过程中发生未处理异常"); return StatusCode(500, $"系统错误: {ex.Message}"); } } } public class UploadFileModel { public IFormFile? File { get; set; } public string? FaceUrl { get; set; } } public class ResultClass { public bool Success { get; set; } public string? Result { get; set; } public int Code { get; set; } public string? Msg { get; set; } } }