246 lines
8.7 KiB
C#
246 lines
8.7 KiB
C#
|
|
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; }
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|