agrobot_base/AgroBase/AgroBase/Services/SyncDataService.cs

205 lines
7.8 KiB
C#

using AgroBase.Forms;
using AgroBase.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using static AgroBase.Models.Enums;
namespace AgroBase.Services
{
public class SyncDataService
{
private static readonly string NomeArquivoSync = "Sync.json";
private static bool Sincronizando { get; set; } = false;
public static async Task<bool> SincronizarArquivosComServidor()
{
if (Sincronizando)
{
return false;
}
// Nao executa a verificacao se estiver em ambiente de teste
if (!Variaveis.Producao)
{
return false;
}
Sincronizando = true;
bool sucesso = true;
if (!Variaveis.OperacaoEmAndamento.Iniciado && APIService.HasInternet)
{
List<string> Operacoes = Directory.GetDirectories(Variaveis.CaminhoOperacoes).ToList();
foreach (string OperacaoID in Operacoes.Select(x => x.Split('/')[1]))
{
string pathArquivoSync = Path.Combine(Variaveis.CaminhoOperacoes, OperacaoID, NomeArquivoSync);
SyncDataModel SyncOperacao = new SyncDataModel()
{
OperacaoID = OperacaoID,
Arquivos = new List<SyncDataArquivoModel>(),
InicioSync = new List<DateTime>(),
FimSync = new List<DateTime>(),
};
SyncOperacao = AtualizarArquivoSync(SyncOperacao, true);
await SyncarArquivos(SyncOperacao);
}
}
Sincronizando = false;
return sucesso;
}
private static SyncDataModel AtualizarArquivoSync(SyncDataModel SyncOperacao, bool Leitura)
{
string pathArquivoSync = Path.Combine(SyncOperacao.Caminho, NomeArquivoSync);
if (Leitura && File.Exists(pathArquivoSync))
{
string json = File.ReadAllText(pathArquivoSync);
try
{
SyncOperacao = JsonConvert.DeserializeObject<SyncDataModel>(json);
}
catch (Exception ex)
{
Console.WriteLine($"Erro ao deserializar arquivo de sync: {ex.Message}");
}
}
else
{
string json = JsonConvert.SerializeObject(SyncOperacao, Formatting.None);
File.WriteAllText(pathArquivoSync, json);
}
return SyncOperacao;
}
private static List<(string caminhoOriginal, string nomeComPrefixo, string subPasta)> ListarArquivosParaSyncar(SyncDataModel SyncOperacao)
{
var arquivosParaSyncar = new List<(string caminhoOriginal, string nomeComPrefixo, string subPasta)>();
// Prefixo para câmeras solo
List<string> camerasSolo = Directory.GetDirectories(SyncOperacao.Caminho).Where(x => x.Contains("Cam_Solo_")).ToList();
foreach (string camSolo in camerasSolo)
{
string sulfixo = "_" + camSolo[camSolo.Length - 1].ToString(); // Define o prefixo baseado na câmera
List<string> imagensSolo = Directory.GetFiles(camSolo).Where(x => x.Contains(".jpg")).ToList();
foreach (var imagem in imagensSolo)
{
string ext = Path.GetExtension(imagem);
string nomeComSulfixo = Path.GetFileName(imagem).Replace(ext, "") + sulfixo + ext; // Adiciona o prefixo no nome da imagem
arquivosParaSyncar.Add((imagem, nomeComSulfixo, "solo")); // Adiciona a pasta "solo"
}
}
// Imagens do caminho (sem prefixo)
List<string> imagensCaminho = Directory.GetFiles(Path.Combine(SyncOperacao.Caminho, T_Code.Knt.ToString())).Where(x => x.Contains("rgb")).ToList();
foreach (var imagemCaminho in imagensCaminho)
{
string nomeComPrefixo = Path.GetFileName(imagemCaminho); // Nome original, sem prefixo
arquivosParaSyncar.Add((imagemCaminho, nomeComPrefixo, "caminho")); // Adiciona a pasta "caminho"
}
// Excluir imagens que já foram sincronizadas
arquivosParaSyncar = arquivosParaSyncar
.Where(x => !SyncOperacao.Arquivos.Select(a => a.Nome).Contains(x.caminhoOriginal))
.ToList();
return arquivosParaSyncar;
}
private static async Task<bool> SyncarArquivos(SyncDataModel SyncOperacao)
{
if (SyncOperacao.Sucesso)
{
return true;
}
SyncOperacao.InicioSync.Add(DateTime.Now);
// Listar os arquivos que precisam ser sincronizados
var arquivosParaSyncar = ListarArquivosParaSyncar(SyncOperacao);
SyncOperacao.Arquivos.AddRange(
arquivosParaSyncar
.Select(x => new SyncDataArquivoModel()
{
Nome = x.caminhoOriginal,
Sucesso = false,
Syncado = false
})
.ToList()
);
if (arquivosParaSyncar.Any())
{
// Compactar os arquivos em um único pacote (mantendo a estrutura de diretórios)
byte[] arquivoCompactado = CompactarArquivos(arquivosParaSyncar);
// Preparar os dados para envio
Dictionary<string, string> body = new Dictionary<string, string>
{
{ "operacaoId", SyncOperacao.OperacaoID }
};
Dictionary<string, byte[]> files = new Dictionary<string, byte[]>
{
{ "imagens.zip", arquivoCompactado }
};
// Enviar o arquivo compactado para o servidor
(bool sucesso, string response) = await APIService.PostAsync("uploadTrainFiles", body, files);
// Atualizar o status de sincronização
foreach (var arquivoSync in SyncOperacao.Arquivos.Where(x => !x.Sucesso))
{
arquivoSync.Syncado = true;
arquivoSync.Sucesso = sucesso;
arquivoSync.SyncadoEm = DateTime.Now;
}
}
SyncOperacao.FimSync.Add(DateTime.Now);
AtualizarArquivoSync(SyncOperacao, false);
return SyncOperacao.Completo;
}
private static byte[] CompactarArquivos(List<(string caminhoOriginal, string nomeComPrefixo, string subPasta)> arquivosParaSyncar)
{
using (var memoryStream = new MemoryStream())
{
using (var zipArchive = new System.IO.Compression.ZipArchive(memoryStream, System.IO.Compression.ZipArchiveMode.Create, true))
{
foreach (var (caminhoOriginal, nomeComPrefixo, subPasta) in arquivosParaSyncar)
{
// Cria a entrada com o caminho da subpasta
var zipEntry = zipArchive.CreateEntry(Path.Combine(subPasta, nomeComPrefixo), System.IO.Compression.CompressionLevel.Optimal);
using (var entryStream = zipEntry.Open())
using (var fileStream = new FileStream(caminhoOriginal, FileMode.Open))
{
fileStream.CopyTo(entryStream);
}
}
}
return memoryStream.ToArray(); // Retorna o byte array do arquivo compactado
}
}
}
}