Modifica metodo scaricamento file JWD da API

This commit is contained in:
Samuele Locatelli
2026-01-13 15:10:47 +01:00
parent e267c70537
commit 15633a06cd
13 changed files with 316 additions and 325 deletions
@@ -14,8 +14,6 @@ using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
using System.Globalization;
using System.Reflection.PortableExecutable;
using System.Security.AccessControl;
using static EgwCoreLib.Lux.Core.Enums;
namespace EgwCoreLib.Lux.Data.Controllers
@@ -1925,6 +1923,32 @@ namespace EgwCoreLib.Lux.Data.Controllers
return dbResult;
}
/// <summary>
/// Recupera da DB riga offerta dato UID
/// </summary>
/// <param name="OfferRowUID"></param>
/// <returns></returns>
internal OfferRowModel? OfferRowGetByUID(string OfferRowUID)
{
OfferRowModel? dbResult = null;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = dbCtx
.DbSetOfferRow
.Include(s => s.SellingItemNav)
.FirstOrDefault(x => x.OfferRowUID == OfferRowUID);
}
catch (Exception exc)
{
Log.Error($"Eccezione durante OfferRowGetByUID{Environment.NewLine}{exc}");
}
}
return dbResult;
}
internal async Task<bool> OffersCheckExpired()
{
bool answ = false;
@@ -2863,6 +2887,32 @@ namespace EgwCoreLib.Lux.Data.Controllers
return dbResult;
}
/// <summary>
/// Riga Ordine dato suo UID
/// </summary>
/// <param name="OrderRowUID"></param>
/// <returns></returns>
internal OrderRowModel OrderRowGetByUID(string OrderRowUID)
{
OrderRowModel? dbResult = null;
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
using (DataLayerContext dbCtx = new DataLayerContext())
{
try
{
dbResult = dbCtx
.DbSetOrderRow
.Include(s => s.SellingItemNav)
.FirstOrDefault(x => x.OrderRowUID == OrderRowUID);
}
catch (Exception exc)
{
Log.Error($"Eccezione durante OrderRowGetByUID{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Validazione record:
/// - controllo state vs estimate
@@ -1044,6 +1044,38 @@ namespace EgwCoreLib.Lux.Data.Services
return result;
}
/// <summary>
/// Riga Offerta dato suo UID
/// </summary>
/// <param name="OfferRowUID"></param>
/// <returns></returns>
public async Task<OfferRowModel?> OfferRowGetByUID(string OfferRowUID)
{
string source = "DB";
Stopwatch sw = new Stopwatch();
sw.Start();
OfferRowModel? result = null;
// cerco in redis...
string currKey = $"{redisBaseKey}:OfferRows:ByUID:{OfferRowUID}";
RedisValue rawData = await redisDb.StringGetAsync(currKey);
//if (!string.IsNullOrEmpty($"{rawData}"))
if (rawData.HasValue)
{
result = JsonConvert.DeserializeObject<OfferRowModel>($"{rawData}");
source = "REDIS";
}
else
{
result = dbController.OfferRowGetByUID(OfferRowUID);
// serializzo e salvo...
rawData = JsonConvert.SerializeObject(result);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
sw.Stop();
Log.Debug($"OfferRowGetByUID | {source} | {sw.Elapsed.TotalMilliseconds}ms");
return result;
}
/// <summary>
/// Verifica offerte scadute, con update sul DB
/// </summary>
@@ -1487,6 +1519,38 @@ namespace EgwCoreLib.Lux.Data.Services
return result;
}
/// <summary>
/// Riga Ordine dato suo UID
/// </summary>
/// <param name="OrderRowUID"></param>
/// <returns></returns>
public async Task<OrderRowModel?> OrderRowGetByUID(string OrderRowUID)
{
string source = "DB";
Stopwatch sw = new Stopwatch();
sw.Start();
OrderRowModel? result = null;
// cerco in redis...
string currKey = $"{redisBaseKey}:OrderRows:ByUID:{OrderRowUID}";
RedisValue rawData = await redisDb.StringGetAsync(currKey);
//if (!string.IsNullOrEmpty($"{rawData}"))
if (rawData.HasValue)
{
result = JsonConvert.DeserializeObject<OrderRowModel>($"{rawData}");
source = "REDIS";
}
else
{
result = dbController.OrderRowGetByUID(OrderRowUID);
// serializzo e salvo...
rawData = JsonConvert.SerializeObject(result);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
sw.Stop();
Log.Debug($"OrderRowGetByUID | {source} | {sw.Elapsed.TotalMilliseconds}ms");
return result;
}
/// <summary>
/// Validazione record:
/// - controllo state vs estimate
+184
View File
@@ -0,0 +1,184 @@
using EgwCoreLib.Lux.Data.Services;
using EgwMultiEngineManager.Data;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using NLog;
using System;
using System.Data;
using System.Diagnostics;
using System.Text;
namespace Lux.API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class FileController : ControllerBase
{
#region Public Constructors
/// <summary>
/// Controller per gestione file (es download JWD)
/// </summary>
/// <param name="imgServ"></param>
/// <param name="logger"></param>
public FileController(DataLayerServices DLService, ImageCacheService imgServ, ILogger<ImageController> logger)
{
_imgService = imgServ;
_DSService = DLService;
_logger = logger;
}
#endregion Public Constructors
#region Public Methods
#if false
/// <summary>
/// Chiamata GET: restituisce file PNG (da file o da cache)
/// PUT: api/image/png/00000000-0000-0000-0000-000000000000
/// </summary>
/// <param name="id">id oggetto</param>
/// <returns></returns>
[HttpGet("png/{id}")]
public async Task<IActionResult> png(string id)
{
Stopwatch sw = new Stopwatch();
sw.Start();
string base64Encoded = "";
byte[] decodedBytes = new byte[0];
// ...se ricevo percorso --> leggo jwd/svg cablato
if (!string.IsNullOrEmpty(id))
{
// bonifica nome svg da
base64Encoded = _imgService.LoadPng(id, EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM);
// converto base64
decodedBytes = Convert.FromBase64String(base64Encoded);
}
sw.Stop();
Log.Info($"pngString | {sw.Elapsed.TotalMilliseconds:N3} ms");
//return Ok(decodedString);
return File(decodedBytes, "image/png");
}
/// <summary>
/// Chiamata GET: riceve Json in formato JwdDto, restituisce svg file
/// GET: api/Jwd/svg/00000000-0000-0000-0000-000000000000
/// </summary>
/// <param name="id">id univoco img</param>
/// <returns></returns>
[HttpGet("svg/{id}")]
public async Task<IActionResult> svgFileGet(string id)
{
Stopwatch sw = new Stopwatch();
sw.Start();
string filePath = Path.Combine("DemoImg", "AntaDoppia.svg");
var svgContent = await System.IO.File.ReadAllTextAsync(filePath);
var bytes = System.Text.Encoding.UTF8.GetBytes(svgContent);
sw.Stop();
_logger.LogInformation($"svgString | {sw.Elapsed.TotalMilliseconds:N3} ms");
return File(bytes, "image/svg+xml");
}
#endif
/// <summary>
/// Chiamata GET: restituisce file di un determinato objType
/// GET: api/file/POR.25.0000000E?env=WINDOW&type=POR
/// GET: api/file/SOR.25.0000000E?env=WINDOW&type=SOR
///
/// nb: al momento solo window e file jwd
/// </summary>
/// <param name="id">uid oggetto</param>
/// <param name="objType">tipologia oggetto (SOR/POR)</param>
/// <param name="env">environment oggetto</param>
/// <returns></returns>
[HttpGet("{id}")]
public async Task<IActionResult> porFile(string id, string objType = "SOR", Constants.EXECENVIRONMENTS env = Constants.EXECENVIRONMENTS.WINDOW)
{
Stopwatch sw = new Stopwatch();
sw.Start();
if (string.IsNullOrEmpty(id))
return NotFound();
// accetta SOLO env window...
if (env != Constants.EXECENVIRONMENTS.WINDOW)
{
return BadRequest("Only Window env");
}
else
{
string mimeType = "txt";
string fileName = id.Replace(".", "_").Replace(" ", "_").Replace(":", "_");
byte[] bytes = new byte[0];
// ...se ricevo percorso --> leggo jwd/svg cablato
if (!string.IsNullOrEmpty(id))
{
// se contiene i caratteri casuali x forzare reload --> li levo
if (id.Contains("-"))
{
id = id.Substring(0, id.IndexOf("-"));
}
// secondo del tipo + enivr decodifico valore corretto
switch (env)
{
case Constants.EXECENVIRONMENTS.NULL:
break;
case Constants.EXECENVIRONMENTS.WINDOW:
mimeType = "application/octet-stream";
fileName = $"{fileName}.jwd";
// recupero riga..
string jsonContent = "";// await _imgService.LoadSvgAsync(id, env);
// a seconda del tipo leggo da 2 aree db diverse...
if (objType == "POR")
{
var currPOR = await _DSService.OrderRowGetByUID(id);
jsonContent = currPOR?.SerStruct ?? "";
}
else if (objType == "SOR")
{
var currSOR = await _DSService.OfferRowGetByUID(id);
jsonContent = currSOR?.SerStruct ?? "";
}
// se NON vuoto --> converto byte stream...
if (!string.IsNullOrEmpty(jsonContent))
{
bytes = Encoding.UTF8.GetBytes(jsonContent);
}
break;
case Constants.EXECENVIRONMENTS.BEAM:
case Constants.EXECENVIRONMENTS.WALL:
case Constants.EXECENVIRONMENTS.CABINET:
default:
mimeType = "image/png";
string base64Encoded = _imgService.LoadPng(id, EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.BEAM);
// converto base64
bytes = Convert.FromBase64String(base64Encoded);
break;
}
}
sw.Stop();
Log.Info($"{mimeType} | {sw.Elapsed.TotalMilliseconds:N3} ms");
return File(bytes, mimeType, fileName);
}
}
#endregion Public Methods
#region Private Fields
private static Logger Log = LogManager.GetCurrentClassLogger();
private readonly ILogger<ImageController> _logger;
#endregion Private Fields
#region Private Properties
private ImageCacheService _imgService { get; set; }
private DataLayerServices _DSService { get; set; }
#endregion Private Properties
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<Version>0.9.2601.1312</Version>
<Version>0.9.2601.1315</Version>
</PropertyGroup>
<ItemGroup>
+4 -2
View File
@@ -193,14 +193,16 @@ else
<span class="small">@fSize(item.FileSize)</span>
</li>
}
@if (PreparedFile.Contains(FixUidName(item.OfferRowUID)))
@* @if (PreparedFile.Contains(FixUidName(item.OfferRowUID)))
{
<li class="list-group-item px-2 py-1 small"><a href="@($"download?fileName={FixUidName(item.OfferRowUID)}.jwd")" target="_blank" class="btn btn-sm btn-success">Download <i class="fa-solid fa-download"></i></a></li>
}
else
{
<li class="list-group-item px-2 py-1 small"><button class="btn btn-sm btn-info" @onclick="() => PrepareFile(item)">Prepare <i class="fa-solid fa-download"></i></button></li>
}
} *@
<li class="list-group-item px-2 py-1 small"><a href="@(DownloadUrl(item.OfferRowUID))" target="_blank" class="btn btn-sm btn-success">Download <i class="fa-solid fa-download"></i></a></li>
</ul>
</td>
@if (CurrEditMode == EditMode.RecData && EditRecord != null && EditRecord.OfferRowID == item.OfferRowID)
+7 -58
View File
@@ -629,50 +629,23 @@ namespace Lux.UI.Components.Compo
protected override async Task OnParametersSetAsync()
{
TempCleanup();
await ReloadData();
UpdateTable();
}
/// <summary>
/// Esegue preparazione del file file:
/// - legge dal DB il contenuto
/// - salva in area temp
/// Prepara URL x download file JWD
/// </summary>
/// <param name="currRec"></param>
/// <param name="currUid"></param>
/// <param name="objType"></param>
/// <param name="envir"></param>
/// <returns></returns>
protected async Task PrepareFile(OfferRowModel currRec)
private string DownloadUrl(string currUid, string objType = "SOR", EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS envir = EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW)
{
// verifico sia un JWD x ora...
if (currRec.Envir == EgwMultiEngineManager.Data.Constants.EXECENVIRONMENTS.WINDOW)
{
string fName = FixUidName($"{currRec.OfferRowUID}");
var filePath = Path.Combine(CurrEnv.ContentRootPath, "temp\\", $"{fName}.jwd");
// verifico la cartella esista...
var parentDir = Path.GetDirectoryName(filePath);
if (parentDir != null && !Directory.Exists(parentDir))
{
Directory.CreateDirectory(parentDir);
}
// salvo il contenuto
File.WriteAllText(filePath, currRec.SerStruct);
// aggiungo a lista preparati se non ci fosse...
if (!PreparedFile.Contains(fName))
{
PreparedFile.Add(fName);
}
}
return $"{apiUrl}/file/{currUid}?objType={objType}&env={envir}";
}
/// <summary>
/// Fix nome UID senza punti intermedi o spazi
/// </summary>
/// <param name="origName"></param>
/// <returns></returns>
private string FixUidName(string origName)
{
return origName.Replace(" ", "_").Replace(".", "_");
}
/// <summary>
/// Lancia la richiesta di ricaolo della BOM dal JWD (o equivalente)
/// </summary>
@@ -1562,30 +1535,6 @@ namespace Lux.UI.Components.Compo
return rawList ?? new List<OfferRowModel>();
}
/// <summary>
/// Pulizia folder temp
/// </summary>
private void TempCleanup()
{
var tempPath = Path.Combine(CurrEnv.ContentRootPath, "temp\\");
var listFiles = Directory.GetFiles(tempPath);
if (listFiles != null && listFiles.Count() > 0)
{
foreach (var cFile in listFiles)
{
// escludo placeholder...
if (!cFile.Contains("placeholder"))
{
var fInfo = File.GetLastWriteTime(cFile);
if (DateTime.Now.Subtract(fInfo).TotalMinutes > 10)
{
File.Delete(cFile);
}
}
}
}
}
/// <summary>
/// Toggle visibilit modifica file indicando ID della OfferRow corrente (o zero se deselect)
/// </summary>
+1 -1
View File
@@ -5,7 +5,7 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>aspnet-Lux.UI-a758c101-a2f4-4e38-977d-1c4887dbbd50</UserSecretsId>
<Version>0.9.2601.1312</Version>
<Version>0.9.2601.1315</Version>
</PropertyGroup>
<ItemGroup>
View File
-93
View File
@@ -1,93 +0,0 @@
{
"ProfilePath": "Profilo78",
"Material": "Pino",
"ColorMaterial": "Black",
"Glass": "Vetro BE 2S 4T/16/4T",
"AreaList": [
{
"Shape": "RECTANGLE",
"DimensionList": [
{
"Index": 1,
"Name": "Width",
"Value": 800.0
},
{
"Index": 2,
"Name": "Height",
"Value": 1400.0
}
],
"JointList": [
{
"Index": 1,
"JointType": "FULL_H"
},
{
"Index": 2,
"JointType": "FULL_H"
},
{
"Index": 3,
"JointType": "FULL_H"
},
{
"Index": 4,
"JointType": "FULL_H"
}
],
"Threshold": "Bottom",
"BottomRail": false,
"BottomRailQty": 0,
"GroupId": 1,
"AreaList": [
{
"IsSashVertical": true,
"SashList": [
{
"SashId": 1,
"OpeningType": "TILTTURN_LEFT",
"MeasureType": "PERCENTAGE",
"Dimension": 100.0,
"HasHandle": true,
"JointList": [
{
"Index": 1,
"JointType": "FULL_V"
},
{
"Index": 2,
"JointType": "FULL_V"
},
{
"Index": 3,
"JointType": "FULL_V"
},
{
"Index": 4,
"JointType": "FULL_V"
}
]
}
],
"SashType": "NULL",
"BottomRail": false,
"BottomRailQty": 0,
"Hardware": "000545",
"HwOptionList": [],
"GroupId": 4,
"AreaList": [
{
"FillType": "GLASS",
"GroupId": 3,
"AreaList": [],
"AreaType": "FILL"
}
],
"AreaType": "SASH"
}
],
"AreaType": "FRAME"
}
]
}
-165
View File
@@ -1,165 +0,0 @@
{
"ProfilePath": "Profilo78",
"Material": "Pino",
"ColorMaterial": "Black",
"Glass": "Vetro BE 2S 4T/16/4T",
"AreaList": [
{
"Shape": "RECTANGLE",
"DimensionList": [
{
"Index": 1,
"Name": "Width",
"Value": 1800.0
},
{
"Index": 2,
"Name": "Height",
"Value": 2100.0
}
],
"JointList": [
{
"Index": 1,
"JointType": "FULL_H"
},
{
"Index": 2,
"JointType": "FULL_H"
},
{
"Index": 3,
"JointType": "FULL_H"
},
{
"Index": 4,
"JointType": "FULL_H"
}
],
"Threshold": "Bottom",
"BottomRail": false,
"BottomRailQty": 0,
"GroupId": 1,
"AreaList": [
{
"IsSashVertical": true,
"SashList": [
{
"SashId": 1,
"OpeningType": "TILTTURN_LEFT",
"MeasureType": "PERCENTAGE",
"Dimension": 50.0,
"HasHandle": true,
"JointList": [
{
"Index": 1,
"JointType": "FULL_V"
},
{
"Index": 2,
"JointType": "FULL_V"
},
{
"Index": 3,
"JointType": "FULL_V"
},
{
"Index": 4,
"JointType": "FULL_V"
}
]
},
{
"SashId": 2,
"OpeningType": "TURNONLY_RIGHT",
"MeasureType": "PERCENTAGE",
"Dimension": 50.0,
"HasHandle": false,
"JointList": [
{
"Index": 1,
"JointType": "FULL_V"
},
{
"Index": 2,
"JointType": "FULL_V"
},
{
"Index": 3,
"JointType": "FULL_V"
},
{
"Index": 4,
"JointType": "FULL_V"
}
]
}
],
"SashType": "NULL",
"BottomRail": false,
"BottomRailQty": 0,
"Hardware": "000548",
"HwOptionList": [
{
"Name": "Entrata",
"Value": "15"
},
{
"Name": "LavManigliaPassante",
"Value": "false"
},
{
"Name": "PosizioneForoCilindro",
"Value": "sopra"
},
{
"Name": "Deviatore",
"Value": "false"
},
{
"Name": "ModelloCilindro",
"Value": "c999"
},
{
"Name": "LavCilindroPassante",
"Value": "false"
},
{
"Name": "HMan",
"Value": "500"
}
],
"GroupId": 4,
"AreaList": [
{
"GroupId": 5,
"AreaList": [
{
"FillType": "GLASS",
"GroupId": 3,
"AreaList": [],
"AreaType": "FILL"
}
],
"AreaType": "SPLITTED"
},
{
"GroupId": 6,
"AreaList": [
{
"FillType": "GLASS",
"GroupId": 7,
"AreaList": [],
"AreaType": "FILL"
}
],
"AreaType": "SPLITTED"
}
],
"AreaType": "SASH"
}
],
"AreaType": "FRAME"
}
]
}
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>LUX - Web Windows MES</i>
<h4>Versione: 0.9.2601.1312</h4>
<h4>Versione: 0.9.2601.1315</h4>
<br /> Note di rilascio:
<ul>
<li>
+1 -1
View File
@@ -1 +1 @@
0.9.2601.1312
0.9.2601.1315
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>0.9.2601.1312</version>
<version>0.9.2601.1315</version>
<url>http://nexus.steamware.net/repository/SWS/GPW/stable/GPW.UI.zip</url>
<changelog>http://nexus.steamware.net/repository/SWS/GPW/stable/ChangeLog.html</changelog>
<mandatory>false</mandatory>