215 lines
8.1 KiB
C#
215 lines
8.1 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
using ListmonkIntegration.Services;
|
|
using ListmonkIntegration.Models;
|
|
using ClosedXML.Excel;
|
|
|
|
namespace ListmonkIntegration.Pages.Subscribers
|
|
{
|
|
public class UploadModel : PageModel
|
|
{
|
|
private readonly IListmonkService _listmonkService;
|
|
private readonly ILogger<UploadModel> _logger;
|
|
|
|
[BindProperty]
|
|
public IFormFile? excelFile { get; set; }
|
|
|
|
public List<Subscriber> Subscribers { get; set; } = new List<Subscriber>();
|
|
public List<string> ColumnHeaders { get; set; } = new List<string>();
|
|
public string Message { get; set; } = string.Empty;
|
|
public bool IsSuccess { get; set; }
|
|
|
|
public UploadModel(IListmonkService listmonkService, ILogger<UploadModel> logger)
|
|
{
|
|
_listmonkService = listmonkService;
|
|
_logger = logger;
|
|
}
|
|
|
|
public void OnGet()
|
|
{
|
|
}
|
|
|
|
public async Task<IActionResult> OnPostAsync(string listName)
|
|
{
|
|
try
|
|
{
|
|
_logger.LogInformation("=== Upload started ===");
|
|
|
|
if (excelFile == null || excelFile.Length == 0)
|
|
{
|
|
Message = "Ôàéë íå âûáðàí";
|
|
IsSuccess = false;
|
|
return Page();
|
|
}
|
|
|
|
_logger.LogInformation($"File received: {excelFile.FileName}, Size: {excelFile.Length} bytes");
|
|
|
|
// Îãðàíè÷åíèå ðàçìåðà ôàéëà (10 MB)
|
|
if (excelFile.Length > 10 * 1024 * 1024)
|
|
{
|
|
Message = "Ôàéë ñëèøêîì áîëüøîé (ìàêñèìóì 10 MB)";
|
|
IsSuccess = false;
|
|
return Page();
|
|
}
|
|
|
|
// ×òåíèå Excel ôàéëà
|
|
_logger.LogInformation("Reading Excel file...");
|
|
Subscribers = ReadExcelFile(excelFile);
|
|
_logger.LogInformation($"Read {Subscribers.Count} subscribers");
|
|
|
|
if (!Subscribers.Any())
|
|
{
|
|
Message = "Íå íàéäåíî ïîäïèñ÷èêîâ â ôàéëå";
|
|
IsSuccess = false;
|
|
return Page();
|
|
}
|
|
|
|
// Ïðîâåðÿåì ïîäêëþ÷åíèå
|
|
_logger.LogInformation("Testing Listmonk connection...");
|
|
if (!await _listmonkService.TestConnectionAsync())
|
|
{
|
|
Message = "Íåò ïîäêëþ÷åíèÿ ê Listmonk";
|
|
IsSuccess = false;
|
|
return Page();
|
|
}
|
|
|
|
// Ñîçäàåì ñïèñîê
|
|
_logger.LogInformation($"Creating list: {listName}");
|
|
int listId = await _listmonkService.CreateListAsync(listName);
|
|
|
|
// Èìïîðòèðóåì
|
|
_logger.LogInformation($"Importing to list {listId}...");
|
|
await _listmonkService.ImportSubscribersAsync(new List<int> { listId }, Subscribers);
|
|
|
|
Message = $"Óñïåøíî çàãðóæåíî {Subscribers.Count} ïîäïèñ÷èêîâ â ñïèñîê \"{listName}\"";
|
|
IsSuccess = true;
|
|
_logger.LogInformation("=== Upload completed successfully ===");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Message = $"Îøèáêà: {ex.Message}";
|
|
IsSuccess = false;
|
|
_logger.LogError(ex, "=== Upload failed ===");
|
|
}
|
|
|
|
return Page();
|
|
}
|
|
|
|
private List<Subscriber> ReadExcelFile(IFormFile file)
|
|
{
|
|
var subscribers = new List<Subscriber>();
|
|
|
|
try
|
|
{
|
|
// Ñîçäà¸ì âðåìåííûé ôàéë ñ ïðàâèëüíûì ðàñøèðåíèåì .xlsx
|
|
var tempFilePath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.xlsx");
|
|
_logger.LogInformation($"Temp file: {tempFilePath}");
|
|
|
|
try
|
|
{
|
|
// Ñîõðàíÿåì çàãðóæåííûé ôàéë âî âðåìåííûé ôàéë
|
|
using (var stream = new FileStream(tempFilePath, FileMode.Create))
|
|
{
|
|
file.CopyTo(stream);
|
|
}
|
|
|
|
_logger.LogInformation("Opening workbook...");
|
|
using (var workbook = new XLWorkbook(tempFilePath))
|
|
{
|
|
var worksheet = workbook.Worksheet(1);
|
|
var firstRow = worksheet.FirstRowUsed();
|
|
|
|
if (firstRow == null)
|
|
{
|
|
_logger.LogWarning("Empty file");
|
|
return subscribers;
|
|
}
|
|
|
|
// Çàãîëîâêè
|
|
var headers = new List<string>();
|
|
foreach (var cell in firstRow.Cells())
|
|
{
|
|
var header = cell.Value.ToString().Trim();
|
|
headers.Add(header);
|
|
_logger.LogInformation($"Header: {header}");
|
|
}
|
|
|
|
ColumnHeaders = headers;
|
|
_logger.LogInformation($"Total headers: {headers.Count}");
|
|
|
|
if (headers.Count < 2)
|
|
{
|
|
_logger.LogError("Need at least 2 columns");
|
|
return subscribers;
|
|
}
|
|
|
|
// Äàííûå
|
|
var lastRow = worksheet.LastRowUsed();
|
|
_logger.LogInformation($"Last row: {lastRow?.RowNumber() ?? 0}");
|
|
|
|
for (int row = 2; row <= lastRow.RowNumber(); row++)
|
|
{
|
|
try
|
|
{
|
|
var email = worksheet.Cell(row, 1).GetValue<string>().Trim();
|
|
if (string.IsNullOrWhiteSpace(email))
|
|
{
|
|
_logger.LogWarning($"Row {row}: empty email, skipping");
|
|
continue;
|
|
}
|
|
|
|
var name = worksheet.Cell(row, 2).GetValue<string>().Trim();
|
|
|
|
var attributes = new Dictionary<string, string>();
|
|
for (int col = 3; col <= headers.Count; col++)
|
|
{
|
|
var value = worksheet.Cell(row, col).GetValue<string>().Trim();
|
|
if (!string.IsNullOrWhiteSpace(value))
|
|
{
|
|
attributes[headers[col - 1]] = value;
|
|
}
|
|
}
|
|
|
|
subscribers.Add(new Subscriber
|
|
{
|
|
Email = email,
|
|
FullName = name,
|
|
Attributes = attributes
|
|
});
|
|
|
|
_logger.LogInformation($"Row {row}: Added {email}");
|
|
}
|
|
catch (Exception rowEx)
|
|
{
|
|
_logger.LogWarning(rowEx, $"Skipping row {row}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
// Óäàëÿåì âðåìåííûé ôàéë
|
|
if (System.IO.File.Exists(tempFilePath))
|
|
{
|
|
try
|
|
{
|
|
System.IO.File.Delete(tempFilePath);
|
|
_logger.LogInformation($"Deleted temp file: {tempFilePath}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogWarning(ex, $"Failed to delete temp file: {tempFilePath}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error reading Excel");
|
|
throw;
|
|
}
|
|
|
|
return subscribers;
|
|
}
|
|
}
|
|
} |