feat: 优化OA用印文件下载逻辑,改进文件提取和错误处理

This commit is contained in:
锦麟 王
2026-04-21 10:05:40 +08:00
parent 2d41e3c6cb
commit 61bf9556cf
+82 -46
View File
@@ -405,11 +405,10 @@ namespace YLErp.Modules.TradeModule
continue;
}
// 3. 判断用印是否完成:fj 字段为空表示未盖完章,有值表示已用印
var fj = flowData.flowInfos?["fj"];
if (fj == null || fj.Type == Newtonsoft.Json.Linq.JTokenType.Null)
// 3. 判断用印是否完成:检查 detailMap 中是否有用印文件
if (!HasStampFiles(flowData.flowInfos))
{
logger.Info($"OA用印未完成,fj为空requestid:{oa.oa_fileid}");
logger.Info($"OA用印未完成,detailMap 中无文件信息requestid:{oa.oa_fileid}");
continue;
}
@@ -471,31 +470,55 @@ namespace YLErp.Modules.TradeModule
}
/// <summary>
/// 下载 OA 用印文件
/// 通过 OA 接口下载用印文件
/// </summary>
/// <param name="fileUrl">文件下载地址</param>
/// <param name="fileId">文件 ID</param>
/// <returns>文件字节数组</returns>
private byte[] DownloadOAFile(string fileUrl)
private byte[] DownloadOAFile(string fileId)
{
try
{
if (string.IsNullOrEmpty(fileUrl))
if (string.IsNullOrEmpty(fileId))
{
return null;
}
logger.Info($"下载OA用印文件: {fileUrl}");
var oaConfigSection = AppManager.GetConfiguration().GetSection("oa_confg");
var baseUrl = oaConfigSection["BaseUrl"];
var downloadFileUrl = oaConfigSection["DownloadFileUrl"];
var systemToken = oaConfigSection["SystemToken"];
var systemName = oaConfigSection["SystemName"];
var response = _httpClient.GetAsync(fileUrl).Result;
response.EnsureSuccessStatusCode();
var fileBytes = response.Content.ReadAsByteArrayAsync().Result;
if (string.IsNullOrEmpty(baseUrl) || string.IsNullOrEmpty(downloadFileUrl))
{
logger.Info("OA下载接口配置不完整");
return null;
}
logger.Info($"下载OA用印文件成功,大小: {fileBytes.Length} 字节");
return fileBytes;
var requestUrl = $"{baseUrl.TrimEnd('/')}/{downloadFileUrl.TrimStart('/')}?fileid={Uri.EscapeDataString(fileId)}&systemToken={Uri.EscapeDataString(systemToken)}&systemName={Uri.EscapeDataString(systemName ?? string.Empty)}";
logger.Info($"通过OA接口下载用印文件: fileid={fileId}");
using (var httpClient = new System.Net.Http.HttpClient { Timeout = TimeSpan.FromMinutes(2) })
{
var response = httpClient.GetAsync(requestUrl).Result;
var fileBytes = response.Content.ReadAsByteArrayAsync().Result;
// 检查返回的是否为错误 JSON
if (response.Content.Headers.ContentType?.MediaType == "application/json" ||
(fileBytes.Length > 0 && fileBytes[0] == (byte)'{'))
{
var responseStr = System.Text.Encoding.UTF8.GetString(fileBytes);
logger.Error($"下载用印文件接口返回错误: {responseStr}");
return null;
}
logger.Info($"通过OA接口下载用印文件成功,大小: {fileBytes.Length} 字节");
return fileBytes;
}
}
catch (Exception ex)
{
logger.Error($"下载OA用印文件失败: {fileUrl}, 错误:{ex.Message}", ex);
logger.Error($"通过OA接口下载用印文件失败: fileid={fileId}, 错误:{ex.Message}", ex);
return null;
}
}
@@ -518,16 +541,15 @@ namespace YLErp.Modules.TradeModule
return new TradeOAResult { TradeId = oa.trade_id, Success = false, Message = "未找到确认书文档" };
}
// 从 fj 字段提取用印文件信息
var fj = queryData.flowInfos?["fj"];
if (!TryExtractFileFromFj(fj, out var fileUrl, out var fileName))
// 从 detailMap 中提取用印文件信息
if (!TryExtractFileFromDetailMap(queryData.flowInfos, out var fileId, out var fileName))
{
logger.Info($"无法从 fj 中提取用印文件信息,contract_code:{oa.contract_code}");
logger.Info($"无法从 detailMap 中提取用印文件信息,contract_code:{oa.contract_code}");
return new TradeOAResult { TradeId = oa.trade_id, Success = false, Message = "无法提取用印文件信息" };
}
// 下载用印文件
var fileBytes = DownloadOAFile(fileUrl);
// 通过 OA 接口下载用印文件
var fileBytes = DownloadOAFile(fileId);
if (fileBytes == null || fileBytes.Length == 0)
{
logger.Info($"未获取到用印文件,contract_code:{oa.contract_code}");
@@ -597,47 +619,61 @@ namespace YLErp.Modules.TradeModule
}
/// <summary>
/// 从 fj 字段尝试提取文件下载地址和文件
/// fj 格式:{"annexId":"url1,url2","annexName":"name1,name2"}
/// 判断 flowInfos 中是否存在用印文件
/// </summary>
private bool TryExtractFileFromFj(Newtonsoft.Json.Linq.JToken fj, out string fileUrl, out string fileName)
private bool HasStampFiles(Newtonsoft.Json.Linq.JObject flowInfos)
{
fileUrl = null;
fileName = null;
if (fj == null || fj.Type == Newtonsoft.Json.Linq.JTokenType.Null)
var detailMap = flowInfos?["detailMap"];
if (detailMap == null || !detailMap.Any())
{
return false;
}
// 如果是字符串,直接当作 URL
if (fj.Type == Newtonsoft.Json.Linq.JTokenType.String)
foreach (var detail in detailMap)
{
fileUrl = fj.ToString();
fileName = Path.GetFileName(fileUrl);
return !string.IsNullOrEmpty(fileUrl);
var fileInfos = detail["gatewayFileRequestFileInfo"];
if (fileInfos != null && fileInfos.Any())
{
return true;
}
}
// 解析 annexId(逗号分隔的 URL 数组)和 annexName(逗号分隔的文件名数组)
var annexIdStr = fj["annexId"]?.ToString();
var annexNameStr = fj["annexName"]?.ToString();
return false;
}
if (!string.IsNullOrEmpty(annexIdStr))
/// <summary>
/// 从 detailMap 中提取用印文件 ID 和文件名
/// </summary>
private bool TryExtractFileFromDetailMap(Newtonsoft.Json.Linq.JObject flowInfos, out string fileId, out string fileName)
{
fileId = null;
fileName = null;
var detailMap = flowInfos?["detailMap"];
if (detailMap == null || !detailMap.Any())
{
fileUrl = annexIdStr.Split(',').Select(s => s.Trim()).FirstOrDefault(s => !string.IsNullOrEmpty(s));
return false;
}
if (!string.IsNullOrEmpty(annexNameStr))
foreach (var detail in detailMap)
{
fileName = annexNameStr.Split(',').Select(s => s.Trim()).FirstOrDefault(s => !string.IsNullOrEmpty(s));
var fileInfos = detail["gatewayFileRequestFileInfo"];
if (fileInfos != null && fileInfos.Any())
{
var firstFile = fileInfos.FirstOrDefault();
if (firstFile != null)
{
fileId = firstFile["id"]?.ToString();
fileName = firstFile["fileName"]?.ToString();
if (!string.IsNullOrEmpty(fileId))
{
return true;
}
}
}
}
if (string.IsNullOrEmpty(fileName) && !string.IsNullOrEmpty(fileUrl))
{
fileName = Path.GetFileName(fileUrl);
}
return !string.IsNullOrEmpty(fileUrl);
return false;
}
/// <summary>