Commit 97f9c6a2 by 何阳

文件配置化,去掉partial class

parent fde99e6e
using System; // See https://aka.ms/new-console-template for more information
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FtpAgent namespace FtpAgent
{ {
public class ApiError public class ApiServerError
{ {
public int Code { get; set; } public int Code { get; set; }
public string? Msg { get; set; } public string? Msg { get; set; }
} }
} }
\ No newline at end of file
using Microsoft.Extensions.Configuration;
namespace FtpAgent
{
public class Config
{
public string CustomerName { get; set; }
public string DeviceNo { get; set; }
public int OcrType { get; set; }
public string OrderNo { get; set; }
public int OrderType { get; set; }
public int PhotoMode { get; set; }
public string Secret { get; set; }
public string TenantId { get; set; }
public string OcrServerUrl { get; set; }
public string OcrApiUrl { get; set; }
public string Ip { get; set; }
public int Port { get; set; }
public string Dir{ get; set; }
public Config(string filePath)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddIniFile(filePath);
IConfiguration config = builder.Build();
CustomerName = config["OCR:customerName"];
DeviceNo = config["OCR:deviceNo"];
OcrType = int.Parse(config["OCR:ocrType"]);
OrderNo = config["OCR:orderNo"];
OrderType = int.Parse( config["OCR:orderType"]);
PhotoMode = int.Parse( config["OCR:photoMode"]);
Secret = config["OCR:secret"];
TenantId = config["OCR:tenantId"];
OcrServerUrl = config["OCR:OCR_SERVER_URL"];
OcrApiUrl = config["OCR:OCR_API_URL"];
Ip = config["OCR:Ip"];
Port = int.Parse(config["OCR:Port"]);
Dir = config["OCR:DIR"];
}
}
}
...@@ -23,7 +23,7 @@ namespace FtpAgent ...@@ -23,7 +23,7 @@ namespace FtpAgent
public override void OnException(MethodContext context) public override void OnException(MethodContext context)
{ {
Log.Error(context.Exception, Msg); Log.Error(context.Exception, Msg);
context.HandledException(this, returnValue:Result.Failure<T,ApiError>( new ApiError() context.HandledException(this, returnValue:Result.Failure<T, ApiServerError>( new ApiServerError()
{ {
Code = 600, Code = 600,
Msg = $"{Msg} 程序错误:{context?.Exception?.Message}" Msg = $"{Msg} 程序错误:{context?.Exception?.Message}"
......
...@@ -7,10 +7,18 @@ ...@@ -7,10 +7,18 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<ApplicationDefinition Include="config.ini" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CSharpFunctionalExtensions" Version="2.40.3" /> <PackageReference Include="CSharpFunctionalExtensions" Version="2.40.3" />
<PackageReference Include="FubarDev.FtpServer" Version="3.1.2" /> <PackageReference Include="FubarDev.FtpServer" Version="3.1.2" />
<PackageReference Include="FubarDev.FtpServer.FileSystem.DotNet" Version="3.1.2" /> <PackageReference Include="FubarDev.FtpServer.FileSystem.DotNet" Version="3.1.2" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Rougamo.Fody" Version="2.1.1" /> <PackageReference Include="Rougamo.Fody" Version="2.1.1" />
<PackageReference Include="Serilog.Formatting.Compact" Version="2.0.0" /> <PackageReference Include="Serilog.Formatting.Compact" Version="2.0.0" />
...@@ -19,4 +27,10 @@ ...@@ -19,4 +27,10 @@
<PackageReference Include="Serilog.Sinks.Trace" Version="3.0.0" /> <PackageReference Include="Serilog.Sinks.Trace" Version="3.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Update="config.ini">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project> </Project>
...@@ -25,6 +25,7 @@ public class OcrRequest ...@@ -25,6 +25,7 @@ public class OcrRequest
{ {
this.ocrFile = ocrFile; this.ocrFile = ocrFile;
uniqueNo = Guid.NewGuid().ToString(); uniqueNo = Guid.NewGuid().ToString();
} }
/// <summary> /// <summary>
......
// See https://aka.ms/new-console-template for more information // See https://aka.ms/new-console-template for more information
public partial class OcrServer
namespace FtpAgent
{ {
public class LinesItem public class LinesItem
{ {
...@@ -17,11 +18,12 @@ public partial class OcrServer ...@@ -17,11 +18,12 @@ public partial class OcrServer
/// <summary> /// <summary>
/// OCR识别结果 /// OCR识别结果
/// </summary> /// </summary>
public List<LinesItem> ?lines { get; set; } public List<LinesItem>? lines { get; set; }
/// <summary> /// <summary>
/// OCR记录ID,后续需要传输匹配接口和提交结果 /// OCR记录ID,后续需要传输匹配接口和提交结果
/// </summary> /// </summary>
public long ocrLogId { get; set; } public long ocrLogId { get; set; }
} }
} }
\ No newline at end of file
...@@ -2,76 +2,74 @@ ...@@ -2,76 +2,74 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using static System.Runtime.InteropServices.JavaScript.JSType;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Text;
using Serilog; using Serilog;
using CSharpFunctionalExtensions; using CSharpFunctionalExtensions;
using CSharpFunctionalExtensions.ValueTasks;
using FtpAgent;
using static OcrServer;
public partial class OcrServer namespace FtpAgent
{ {
public static string OCR_SERVER_URL { get; private set; } = "https://hardware-test.guke.tech"; public partial class OcrServer
public static string OCR_API_URL { get; private set; } = "/api/service/ocr/v2/recognize";
[ErrorHandler<OcrResultData>("上传图片到OCR服务器失败!")]
public static async Task<Result<OcrResultData, ApiError>> UploadFile(OcrRequest result)
{ {
string url = $"{OCR_SERVER_URL}{OCR_API_URL}?ocrChannel=1&ocrType=4&remark=certificate test"; public static string OCR_SERVER_URL { get; private set; } = "https://hardware-test.guke.tech";
using (var httpclient = new HttpClient()) public static string OCR_API_URL { get; private set; } = "/api/service/ocr/v2/recognize";
[ErrorHandler<OcrResultData>("上传图片到OCR服务器失败!")]
public static async Task<Result<OcrResultData, ApiServerError>> UploadFile(OcrRequest result)
{ {
var formData = new MultipartFormDataContent(); string url = $"{OCR_SERVER_URL}{OCR_API_URL}?ocrChannel=1&ocrType=4&remark=certificate test";
formData.AddFile(result.ocrFile); using (var httpclient = new HttpClient())
formData.AddJson(result);
Log.Information("Post请求:{url},上传文件:{file},请求参数:", url, result.ocrFile);
await LogFormDataContent(formData);
var response = await httpclient.PostAsync(url, formData);
var responseContent = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{ {
Log.Error($"请求远程OCR服务器失败,失败code=${response.StatusCode}, msg={responseContent}"); var formData = new MultipartFormDataContent();
return Result.Failure<OcrResultData, ApiError>(new ApiError() { Code = (int)response.StatusCode, Msg = responseContent }); formData.AddFile(result.ocrFile);
formData.AddJson(result);
Log.Information("Post请求:{url},上传文件:{file},请求参数:", url, result.ocrFile);
await LogFormDataContent(formData);
var response = await httpclient.PostAsync(url, formData);
var responseContent = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
Log.Error($"请求远程OCR服务器失败,失败code=${response.StatusCode}, msg={responseContent}");
return Result.Failure<OcrResultData, ApiServerError>(new ApiServerError() { Code = (int)response.StatusCode, Msg = responseContent });
}
Log.Information("Post请求:{url},请求结果:{responseContent}", url, responseContent);
var respond = JsonConvert.DeserializeObject<Respond<OcrResultData>>(responseContent);
if (respond.code != 200)
{
Log.Error($"请求远程OCR API失败,失败code=${respond.code}, msg={respond.detail}");
return Result.Failure<OcrResultData, ApiServerError>(new ApiServerError() { Code = respond.code, Msg = respond.msg });
}
var test = respond?.data?.lines.Select(item => item.text).Aggregate((l, f) => l + f);
Log.Information($"返回结果文本长度:{test.Length}");
return Result.Success<OcrResultData, ApiServerError>(respond.data);
} }
Log.Information("Post请求:{url},请求结果:{responseContent}", url, responseContent);
var respond = JsonConvert.DeserializeObject<Respond<OcrResultData>>(responseContent);
if (respond.code != 200)
{
Log.Error($"请求远程OCR API失败,失败code=${respond.code}, msg={respond.detail}");
return Result.Failure<OcrResultData, ApiError>(new ApiError() { Code = respond.code, Msg = respond.msg }) ;
}
var test = respond?.data?.lines.Select(item => item.text).Aggregate((l, f) => l + f);
Log.Information($"返回结果文本长度:{test.Length}");
return Result.Success<OcrResultData, ApiError>(respond.data);
} }
}
public static async Task LogFormDataContent(MultipartFormDataContent formData) public static async Task LogFormDataContent(MultipartFormDataContent formData)
{
var logData = new Dictionary<string, object>();
foreach (var content in formData)
{ {
ContentDispositionHeaderValue disposition = content.Headers.ContentDisposition; var logData = new Dictionary<string, object>();
string name = disposition.Name?.Trim('"');
string? fileName = disposition.FileName?.Trim('"');
if (content is StringContent || content.Headers.ContentType?.MediaType == "text/plain") foreach (var content in formData)
{
string value = await content.ReadAsStringAsync();
logData.Add(name, value);
}
else if (fileName != null)
{
logData.Add(name, $"(File: {fileName})");
}
else
{ {
logData.Add(name, $"(Content-Type: {content.Headers.ContentType})"); ContentDispositionHeaderValue disposition = content.Headers.ContentDisposition;
string name = disposition.Name?.Trim('"');
string? fileName = disposition.FileName?.Trim('"');
if (content is StringContent || content.Headers.ContentType?.MediaType == "text/plain")
{
string value = await content.ReadAsStringAsync();
logData.Add(name, value);
}
else if (fileName != null)
{
logData.Add(name, $"(File: {fileName})");
}
else
{
logData.Add(name, $"(Content-Type: {content.Headers.ContentType})");
}
} }
}
string json = JsonConvert.SerializeObject(logData, Formatting.Indented); string json = JsonConvert.SerializeObject(logData, Formatting.Indented);
Log.Information("Form Data Content: {FormData}", json); Log.Information("Form Data Content: {FormData}", json);
}
} }
} }
\ No newline at end of file
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
using CaptureAgent; using CaptureAgent;
using FtpAgent;
using FubarDev.FtpServer; using FubarDev.FtpServer;
using FubarDev.FtpServer.FileSystem.DotNet; using FubarDev.FtpServer.FileSystem.DotNet;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
...@@ -9,12 +10,29 @@ using Serilog; ...@@ -9,12 +10,29 @@ using Serilog;
HashSet<string> FileChangeCnt = new(); HashSet<string> FileChangeCnt = new();
Logging.InitLogging(); Logging.InitLogging();
var config = new Config("config.ini");
Log.Information($"Customer Name: {config.CustomerName}");
Log.Information($"Device No: {config.DeviceNo}");
Log.Information($"OCR Type: {config.OcrType}");
Log.Information($"Order No: {config.OrderNo}");
Log.Information($"Order Type: {config.OrderType}");
Log.Information($"Photo Mode: {config.PhotoMode}");
Log.Information($"Secret: {config.Secret}");
Log.Information($"Tenant Id: {config.TenantId}");
Log.Information($"OCR Server URL: {config.OcrServerUrl}");
Log.Information($"OCR API URL: {config.OcrApiUrl}");
Log.Information($"IP: {config.Ip}");
Log.Information($"Port: {config.Port}");
Log.Information($"Dir: {config.Dir}");
// Setup dependency injection // Setup dependency injection
var services = new ServiceCollection(); var services = new ServiceCollection();
// use %TEMP%/TestFtpServer as root folder // use %TEMP%/TestFtpServer as root folder
services.Configure<DotNetFileSystemOptions>(opt => opt services.Configure<DotNetFileSystemOptions>(opt => opt
.RootPath = Path.Combine(Environment.CurrentDirectory, "Test")); .RootPath = Path.Combine(Environment.CurrentDirectory, config.Dir));
// Add FTP server services // Add FTP server services
// DotNetFileSystemProvider = Use the .NET file system functionality // DotNetFileSystemProvider = Use the .NET file system functionality
...@@ -23,11 +41,14 @@ services.AddFtpServer(builder => builder ...@@ -23,11 +41,14 @@ services.AddFtpServer(builder => builder
.UseDotNetFileSystem() // Use the .NET file system functionality .UseDotNetFileSystem() // Use the .NET file system functionality
.EnableAnonymousAuthentication()); // allow anonymous logins .EnableAnonymousAuthentication()); // allow anonymous logins
// Configure the FTP server // Configure the FTP server
services.Configure<FtpServerOptions>(opt => services.Configure<FtpServerOptions>(opt =>
{ {
opt.ServerAddress = "127.0.0.1"; opt.ServerAddress = config.Ip;
opt.Port = 9527; opt.Port = config.Port;
}); });
// Build the service provider // Build the service provider
...@@ -35,13 +56,13 @@ using (var serviceProvider = services.BuildServiceProvider()) ...@@ -35,13 +56,13 @@ using (var serviceProvider = services.BuildServiceProvider())
{ {
Log.Information("开始运行FTP服务"); Log.Information("开始运行FTP服务");
Directory.CreateDirectory("Test"); Directory.CreateDirectory(config.Dir);
// Initialize the FTP server // Initialize the FTP server
var ftpServerHost = serviceProvider.GetRequiredService<IFtpServerHost>(); var ftpServerHost = serviceProvider.GetRequiredService<IFtpServerHost>();
// 设置文件系统监控器 // 设置文件系统监控器
var watcher = new FileSystemWatcher("Test"); var watcher = new FileSystemWatcher(config.Dir);
// 监控的文件类型 // 监控的文件类型
watcher.Filter = "*.*"; watcher.Filter = "*.*";
// 添加事件处理器 // 添加事件处理器
...@@ -52,7 +73,7 @@ using (var serviceProvider = services.BuildServiceProvider()) ...@@ -52,7 +73,7 @@ using (var serviceProvider = services.BuildServiceProvider())
watcher.EnableRaisingEvents = true; watcher.EnableRaisingEvents = true;
// Start the FTP server // Start the FTP server
await ftpServerHost.StartAsync(CancellationToken.None); await ftpServerHost.StartAsync(CancellationToken.None);
Console.WriteLine("输入q退出"); Log.Information("输入q退出");
while (Console.ReadKey().Key != ConsoleKey.Q) while (Console.ReadKey().Key != ConsoleKey.Q)
{ {
...@@ -79,7 +100,17 @@ async void Watcher_Changed(object sender, FileSystemEventArgs e) ...@@ -79,7 +100,17 @@ async void Watcher_Changed(object sender, FileSystemEventArgs e)
if (Path.GetExtension(e.Name) == ".jpg") if (Path.GetExtension(e.Name) == ".jpg")
{ {
Log.Information("{Name} 文件转发到服务器", e.Name); Log.Information("{Name} 文件转发到服务器", e.Name);
OcrRequest result = new OcrRequest(e.FullPath); OcrRequest result = new OcrRequest(e.FullPath)
{
deviceNo = config.DeviceNo,
customerName = config.CustomerName,
ocrType = config.OcrType,
orderNo = config.OrderNo,
orderType = config.OrderType,
photoMode = config.PhotoMode,
secret = config.Secret,
tenantId = config.TenantId,
};
await OcrServer.UploadFile(result); await OcrServer.UploadFile(result);
} }
FileChangeCnt.Remove(e.Name); FileChangeCnt.Remove(e.Name);
......
// See https://aka.ms/new-console-template for more information // See https://aka.ms/new-console-template for more information
public partial class OcrServer namespace FtpAgent
{ {
public record Respond<T> where T: class
public record Respond<T> where T : class
{ {
public Respond(int code, string msg, T data) public Respond(int code, string msg, T data)
{ {
...@@ -33,6 +34,6 @@ public partial class OcrServer ...@@ -33,6 +34,6 @@ public partial class OcrServer
/// <summary> /// <summary>
/// 异常信息 /// 异常信息
/// </summary> /// </summary>
public string ?detail { get; set; } public string? detail { get; set; }
} }
} }
\ No newline at end of file
[OCR]
customerName=无境创新
deviceNo=CS
ocrType=4
orderNo=1
orderType=1
photoMode=1
secret=knz2r23rdhnbnhc7zr9b9ux7evkvzvdm
tenantId=0
OCR_SERVER_URL=https://hardware-test.guke.tech
OCR_API_URL=/api/service/ocr/v2/recognize
Ip=127.0.0.1
Port=9527
DIR=Image
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment