Files
Web_FaceValidator_Dev/Controllers/FaceFeatureController.cs

246 lines
8.7 KiB
C#
Raw Normal View History

2025-11-26 11:14:33 +08:00
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<FaceFeatureController> _logger;
public FaceFeatureController(
IWebHostEnvironment hostingEnvironment,
ILogger<FaceFeatureController> logger)
{
_hostingEnvironment = hostingEnvironment;
_logger = logger;
}
/// <summary>
/// 提交人脸Url/File
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> 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<string> 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<string> 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<IActionResult> 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; }
}
}