Guía de Integración para Clientes C# / .NET
Implementa la descarga de actualizaciones de 250 MB en tus aplicaciones o sistema POS.
Endpoints API Disponibles
GET
/api/updates/latest
Obtiene JSON con la última versión disponible y hash SHA256.
GET
/api/updates/check?currentVersion=1.0.0
Retorna 200 con detalles si hay versión superior, o 204 si está al día.
GET
/api/updates/download/{fileName}
Descarga el ejecutable con soporte para HTTP Range (descargas reanudables).
Código C# Auto-Updater con Reanudación de Descargas
Servicio en C# con soporte para **HTTP Range (resume)**. Si la conexión de 250 MB se interrumpe, se reanuda automáticamente en el punto exacto.
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text.Json;
using System.Threading.Tasks;
using System.Diagnostics;
public class AutoUpdaterService
{
private readonly HttpClient _httpClient;
private readonly string _serverUrl;
public AutoUpdaterService(string serverUrl)
{
_serverUrl = serverUrl.TrimEnd('/');
_httpClient = new HttpClient();
}
public async Task CheckAndApplyUpdateAsync(string currentVersion, Action<double, string> onProgress = null)
{
string checkUrl = $"{_serverUrl}/api/updates/check?currentVersion={currentVersion}";
var response = await _httpClient.GetAsync(checkUrl);
if (response.StatusCode == System.Net.HttpStatusCode.NoContent)
{
Console.WriteLine("El sistema ya está actualizado a la última versión.");
return;
}
response.EnsureSuccessStatusCode();
string json = await response.Content.ReadAsStringAsync();
using var doc = JsonDocument.Parse(json);
var root = doc.RootElement;
string latestVersion = root.GetProperty("version").GetString();
string downloadUrl = root.GetProperty("downloadUrl").GetString();
string expectedSha256 = root.GetProperty("sha256Hash").GetString();
long totalBytes = root.GetProperty("fileSizeBytes").GetInt64();
string fileName = root.GetProperty("fileName").GetString();
string tempFilePath = Path.Combine(Path.GetTempPath(), fileName);
// 1. Soporte para reanudar descarga si ya existían MB descargados
long existingLength = File.Exists(tempFilePath) ? new FileInfo(tempFilePath).Length : 0;
using (var request = new HttpRequestMessage(HttpMethod.Get, downloadUrl))
{
if (existingLength > 0 && existingLength < totalBytes)
{
request.Headers.Range = new RangeHeaderValue(existingLength, null);
Console.WriteLine($"Reanudando descarga de {existingLength / (1024.0 * 1024.0):F1} MB...");
}
using var downloadResponse = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
downloadResponse.EnsureSuccessStatusCode();
using var streamToReadFrom = await downloadResponse.Content.ReadAsStreamAsync();
using var streamToWriteTo = new FileStream(tempFilePath, existingLength > 0 ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.None);
byte[] buffer = new byte[81920];
long totalRead = existingLength;
int bytesRead;
while ((bytesRead = await streamToReadFrom.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await streamToWriteTo.WriteAsync(buffer, 0, bytesRead);
totalRead += bytesRead;
if (totalBytes > 0 && onProgress != null)
{
double percent = (double)totalRead / totalBytes * 100.0;
string speedText = $"{totalRead / (1024.0 * 1024.0):F1} MB / {totalBytes / (1024.0 * 1024.0):F1} MB";
onProgress(percent, speedText);
}
}
}
// 2. Verificar Hash SHA256
string computedHash = ComputeSha256(tempFilePath);
if (!computedHash.Equals(expectedSha256, StringComparison.OrdinalIgnoreCase))
{
File.Delete(tempFilePath);
throw new InvalidDataException("La verificación SHA256 falló. El archivo está dañado.");
}
Console.WriteLine("Integridad SHA256 verificada. Ejecutando instalador...");
// 3. Ejecutar instalador silencioso
Process.Start(new ProcessStartInfo
{
FileName = tempFilePath,
Arguments = "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART",
UseShellExecute = true
});
Environment.Exit(0);
}
private static string ComputeSha256(string filePath)
{
using var sha256 = SHA256.Create();
using var stream = File.OpenRead(filePath);
byte[] hash = sha256.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}