415 lines
14 KiB
C#
415 lines
14 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using System.Text.RegularExpressions;
|
|
using System.Xml;
|
|
using System.Xml.Linq;
|
|
|
|
namespace EFCDesk.Classes
|
|
{
|
|
public static class Helpers
|
|
{
|
|
|
|
// Lista de extensiones permitidas
|
|
private static readonly HashSet<string> ExtensionesPermitidas = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
".jpg",
|
|
".jpeg",
|
|
".png",
|
|
".gif",
|
|
".bmp",
|
|
".pdf",
|
|
".txt",
|
|
".csv"
|
|
};
|
|
|
|
// Lista de extensiones prohibidas (opcional, para mayor seguridad)
|
|
private static readonly HashSet<string> ExtensionesProhibidas = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
".exe",
|
|
".bat",
|
|
".cmd",
|
|
".msi",
|
|
".sh",
|
|
".js",
|
|
".vbs",
|
|
".ps1",
|
|
".jar",
|
|
".com",
|
|
".msp",
|
|
".scr",
|
|
".docm",
|
|
".xlsm",
|
|
".pptm"
|
|
};
|
|
|
|
public static bool ValidarArchivo(string rutaArchivo)
|
|
{
|
|
string extension = Path.GetExtension(rutaArchivo);
|
|
|
|
// Revisar primero si está en la lista prohibida
|
|
if (ExtensionesProhibidas.Contains(extension))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//// Solo permitir si está en la lista de permitidas
|
|
//return ExtensionesPermitidas.Contains(extension);
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Obtiene el tamaño de un archivo en bytes.
|
|
/// </summary>
|
|
/// <param name="rutaArchivo">Ruta completa del archivo.</param>
|
|
/// <returns>Tamaño en bytes, o -1 si el archivo no existe.</returns>
|
|
public static long ObtenerTamanoEnBytes(string rutaArchivo)
|
|
{
|
|
if (!File.Exists(rutaArchivo))
|
|
return -1;
|
|
|
|
FileInfo info = new FileInfo(rutaArchivo);
|
|
return info.Length;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Obtiene el tamaño de un archivo en formato legible (KB, MB, GB).
|
|
/// </summary>
|
|
/// <param name="rutaArchivo">Ruta completa del archivo.</param>
|
|
/// <returns>Cadena con el tamaño formateado, o mensaje de error.</returns>
|
|
public static string ObtenerTamanoFormateado(string rutaArchivo)
|
|
{
|
|
if (!File.Exists(rutaArchivo))
|
|
return "El archivo no existe";
|
|
|
|
long bytes = new FileInfo(rutaArchivo).Length;
|
|
|
|
string[] sufijos = { "B", "KB", "MB", "GB", "TB" };
|
|
int indice = 0;
|
|
double tamaño = bytes;
|
|
|
|
while (tamaño >= 1024 && indice < sufijos.Length - 1)
|
|
{
|
|
tamaño /= 1024;
|
|
indice++;
|
|
}
|
|
|
|
return $"{tamaño:0.##} {sufijos[indice]}";
|
|
}
|
|
/// <summary>
|
|
/// Obtiene la url del endpoint para obtener el pedimento.
|
|
/// </summary>
|
|
/// <returns>Cadena del endpoint.</returns>
|
|
public static string ObtenerEndpointPedimentos()
|
|
{
|
|
return @"/api/v1/customs/pedimentos/?pedimento_app=";
|
|
}
|
|
/// <summary>
|
|
/// Obtiene la url del endpoint para obtener el documento.
|
|
/// </summary>
|
|
/// <returns>Cadena del endpoint.</returns>
|
|
public static string ObtenerEndpointDocumentos()
|
|
{
|
|
return @"/api/v1/record/documents/";
|
|
}
|
|
public static string CrearEndpointpedimentoDesk()
|
|
{
|
|
// return @"/api/v1/customs/pedimentos/bulk-create-pedimento_desk/";
|
|
// return @"/api/v1/customs/pedimentos/bulk-upload-record-zip/";
|
|
return @"/api/v1/customs/pedimentos/bulk-upload-record-zip-async/";
|
|
}
|
|
/// <summary>
|
|
/// Espera hasta que todos los archivos dentro de la carpeta estén libres (no en uso)
|
|
/// </summary>
|
|
public static bool EsperarArchivosListos(string carpetaRaiz, int timeoutSegundos = 30)
|
|
{
|
|
var archivos = Directory.GetFiles(carpetaRaiz, "*.*", SearchOption.AllDirectories);
|
|
var inicio = DateTime.Now;
|
|
|
|
while ((DateTime.Now - inicio).TotalSeconds < timeoutSegundos)
|
|
{
|
|
bool todosListos = true;
|
|
|
|
foreach (var archivo in archivos)
|
|
{
|
|
try
|
|
{
|
|
using (FileStream stream = new FileStream(archivo, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
|
|
{
|
|
// Archivo disponible
|
|
}
|
|
}
|
|
catch (IOException)
|
|
{
|
|
todosListos = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (todosListos)
|
|
return true;
|
|
|
|
Thread.Sleep(500);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Obtiene la carpeta raíz según aplicaWinsaii
|
|
/// </summary>
|
|
public static (string RutaRaiz, string NombreRaiz) ObtenerCarpetaRaiz(string ruta)
|
|
{
|
|
SQLiteHelper sqliteHelper = new SQLiteHelper(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "historico.db"));
|
|
ConfiguracionExpediente config = ConfiguracionExpediente.ObtenerDesdeBaseDeDatos(sqliteHelper);
|
|
bool aplicaWinsaii = config.UsarEstructuraPedimentosWinsaai;
|
|
|
|
string? carpetaActual = EsCarpeta(ruta) ? ruta : Path.GetDirectoryName(ruta);
|
|
string carpetaBase = Path.GetFullPath(config.FolderParaGenerarExpediente);
|
|
carpetaActual = Path.GetFullPath(carpetaActual);
|
|
|
|
string[] segmentosBase = carpetaBase.Trim(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar);
|
|
string[] segmentosActual = carpetaActual.Trim(Path.DirectorySeparatorChar).Split(Path.DirectorySeparatorChar);
|
|
|
|
int nivelDeseado = aplicaWinsaii ? segmentosBase.Length + 2 : segmentosBase.Length + 1;
|
|
|
|
if (segmentosActual.Length > nivelDeseado)
|
|
segmentosActual = segmentosActual.Take(nivelDeseado).ToArray();
|
|
|
|
string carpetaRaiz = string.Join(Path.DirectorySeparatorChar.ToString(), segmentosActual);
|
|
if (!Path.IsPathRooted(carpetaRaiz))
|
|
carpetaRaiz = Path.DirectorySeparatorChar + carpetaRaiz;
|
|
|
|
string nombreRaiz = Path.GetFileName(carpetaRaiz);
|
|
return (carpetaRaiz, nombreRaiz);
|
|
|
|
|
|
}
|
|
public static bool EsCarpeta(string ruta)
|
|
{
|
|
return Directory.Exists(ruta);
|
|
}
|
|
|
|
public static string DominioExpedienteElectronico()
|
|
{
|
|
string efc = Properties.Settings.Default.urlEFC as string;
|
|
return efc;
|
|
}
|
|
|
|
public static bool EsValidaNomeclaturaCarpeta(string pathCarpeta)
|
|
{
|
|
var nombre = Path.GetFileName(pathCarpeta);
|
|
string pattern = @"^\d{2}-\d{4}-\d{7}$|^\d{2}-\d{2}-\d{4}-\d{7}$";
|
|
bool esValido = System.Text.RegularExpressions.Regex.IsMatch(nombre, pattern);
|
|
if (!esValido)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public static bool EsValidaNomeclaturaSAAIM3(string pathArchivo)
|
|
{
|
|
var nombre = Path.GetFileName(pathArchivo);
|
|
string pattern = @"^[m|M]\d{7}\.\d{3}$";
|
|
bool esValido = System.Text.RegularExpressions.Regex.IsMatch(nombre, pattern);
|
|
if (!esValido)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public static bool EsArchivoXMl(string rutaArchivo)
|
|
{
|
|
try
|
|
{
|
|
|
|
string extension = Path.GetExtension(rutaArchivo);
|
|
if (!extension.Equals(".xml", StringComparison.OrdinalIgnoreCase))
|
|
return false;
|
|
|
|
XDocument xdoc = XDocument.Load(rutaArchivo);
|
|
|
|
|
|
}
|
|
catch (XmlException exception)
|
|
{
|
|
Globales.logger.LogError("Helpers - EsArchivoXML", exception);
|
|
return false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Globales.logger.LogError("Helpers - EsArchivoXML", ex);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public static byte[] CrearZipEnMemoria(string nombreArchivo, byte[] contenido)
|
|
{
|
|
try
|
|
{
|
|
using (var memoryStream = new MemoryStream())
|
|
{
|
|
using (var zip = new System.IO.Compression.ZipArchive(memoryStream, System.IO.Compression.ZipArchiveMode.Create, leaveOpen: true))
|
|
{
|
|
|
|
// Aquí puedes agregar archivos al archivo ZIP si es necesario
|
|
var entry = zip.CreateEntry(nombreArchivo);
|
|
|
|
using (var entryStream = entry.Open())
|
|
{
|
|
entryStream.Write(contenido, 0, contenido.Length);
|
|
}
|
|
|
|
}
|
|
return memoryStream.ToArray();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// Manejo de la excepción (puedes registrar el error o lanzar una excepción personalizada)
|
|
Globales.logger.LogError("Helpers", ex);
|
|
|
|
return Array.Empty<byte>();
|
|
}
|
|
|
|
}
|
|
|
|
public static string CalcularHashMD5(string rutaArchivo)
|
|
{
|
|
using (var md5 = MD5.Create())
|
|
{
|
|
using (var stream = File.OpenRead(rutaArchivo))
|
|
{
|
|
var hashBytes = md5.ComputeHash(stream);
|
|
StringBuilder sb = new StringBuilder();
|
|
foreach (var b in hashBytes)
|
|
{
|
|
sb.Append(b.ToString("x2"));
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Crea un ZIP de un solo archivo en una carpeta temporal única.
|
|
/// </summary>
|
|
/// <param name="rutaArchivo">Archivo a comprimir.</param>
|
|
/// <param name="nombreArchivoZip">Nombre del ZIP que se generará.</param>
|
|
/// <param name="autoLimpiar">Si es true, borra la carpeta temporal automáticamente después de crear el ZIP.</param>
|
|
/// <returns>Ruta completa del ZIP generado.</returns>
|
|
public static string CrearZipArchivoEnTemp(string rutaArchivo, string nombreArchivoZip, bool autoLimpiar = false)
|
|
{
|
|
// Obtiene la ruta raíz de la carpeta temporal del sistema
|
|
string tempRoot = Path.Combine(Path.GetTempPath(), "temp-efc-desk");
|
|
//string tempRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),"tempEFCDesk");
|
|
|
|
// Crea una subcarpeta temporal única
|
|
string tempFolder = Path.Combine(tempRoot, Guid.NewGuid().ToString().ToLower().Replace("-","").Substring(0,8));
|
|
Directory.CreateDirectory(tempFolder);
|
|
|
|
// Ruta completa del archivo ZIP dentro de la carpeta temporal
|
|
string zipPath = Path.Combine(tempFolder, nombreArchivoZip);
|
|
|
|
try
|
|
{
|
|
// Verifica que el archivo exista
|
|
if (!File.Exists(rutaArchivo))
|
|
{
|
|
throw new FileNotFoundException($"El archivo no existe: {rutaArchivo}");
|
|
}
|
|
|
|
// Crea el ZIP y agrega el archivo
|
|
using (var zip = ZipFile.Open(zipPath, ZipArchiveMode.Create))
|
|
{
|
|
zip.CreateEntryFromFile(rutaArchivo, Path.GetFileName(rutaArchivo));
|
|
}
|
|
|
|
return zipPath;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Globales.logger.LogError("Helpers - CrearZipArchivoEnTemp", ex);
|
|
return "";
|
|
}
|
|
finally
|
|
{
|
|
if (autoLimpiar)
|
|
{
|
|
try
|
|
{
|
|
// Espera un momento para asegurarse de que el ZIP no esté bloqueado
|
|
System.Threading.Thread.Sleep(3000);
|
|
|
|
// Borra toda la carpeta temporal
|
|
if (Directory.Exists(tempFolder))
|
|
{
|
|
Directory.Delete(tempFolder, true);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Globales.logger.LogError("Helpers - No se pudo limpiar la carpeta temporal", ex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static string CrearZipMultipleArchivos(string[] rutasArchivos, string nombreArchivoZip, bool autoLimpiar = false)
|
|
{
|
|
string tempRoot = Path.Combine(Path.GetTempPath(), "temp-efc-desk");
|
|
string tempFolder = Path.Combine(tempRoot, Guid.NewGuid().ToString().ToLower().Replace("-", "").Substring(0, 8));
|
|
Directory.CreateDirectory(tempFolder);
|
|
|
|
string zipPath = Path.Combine(tempFolder, nombreArchivoZip);
|
|
|
|
try
|
|
{
|
|
using (var zip = ZipFile.Open(zipPath, ZipArchiveMode.Create))
|
|
{
|
|
foreach (var rutaArchivo in rutasArchivos)
|
|
{
|
|
if (File.Exists(rutaArchivo))
|
|
{
|
|
zip.CreateEntryFromFile(rutaArchivo, Path.GetFileName(rutaArchivo));
|
|
}
|
|
}
|
|
}
|
|
|
|
return zipPath;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Globales.logger.LogError("Helpers - CrearZipMultipleArchivos", ex);
|
|
return "";
|
|
}
|
|
finally
|
|
{
|
|
if (autoLimpiar)
|
|
{
|
|
try
|
|
{
|
|
System.Threading.Thread.Sleep(3000);
|
|
if (Directory.Exists(tempFolder))
|
|
{
|
|
Directory.Delete(tempFolder, true);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Globales.logger.LogError("Helpers - No se pudo limpiar carpeta temporal en CrearZipMultipleArchivos", ex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|