Files
CROWLER/Services/PdfStorageService.cs
2026-04-04 10:52:30 +03:00

92 lines
3.1 KiB
C#

using System.IO;
using System.Linq;
using CRAWLER.Configuration;
using Microsoft.Extensions.Configuration;
namespace CRAWLER.Services;
internal sealed class PdfStorageService
{
private readonly KtoPoveritClient _client;
private readonly string _rootPath;
public PdfStorageService(IConfiguration configuration, KtoPoveritClient client)
{
_client = client;
var options = configuration.GetSection("Crawler").Get<CrawlerOptions>()
?? throw new InvalidOperationException("Раздел Crawler не найден в appsettings.json.");
_rootPath = Environment.ExpandEnvironmentVariables(options.PdfStoragePath);
Directory.CreateDirectory(_rootPath);
}
public async Task<string> DownloadAsync(string sourceUrl, string registryNumber, string title, CancellationToken cancellationToken)
{
var bytes = await _client.GetBytesAsync(sourceUrl, cancellationToken);
var fullPath = BuildTargetPath(registryNumber, title, sourceUrl);
await File.WriteAllBytesAsync(fullPath, bytes, cancellationToken);
return fullPath;
}
public async Task<string> CopyFromLocalAsync(string sourcePath, string registryNumber, string title, CancellationToken cancellationToken)
{
var fullPath = BuildTargetPath(registryNumber, title, sourcePath);
await using var sourceStream = File.Open(sourcePath, FileMode.Open, FileAccess.Read, FileShare.Read);
await using var targetStream = File.Create(fullPath);
await sourceStream.CopyToAsync(targetStream, cancellationToken);
return fullPath;
}
public void TryDelete(string path)
{
try
{
if (!string.IsNullOrWhiteSpace(path) && File.Exists(path))
{
File.Delete(path);
}
}
catch
{
}
}
private string BuildTargetPath(string registryNumber, string title, string sourceIdentity)
{
var safeFolder = MakeSafePathSegment(string.IsNullOrWhiteSpace(registryNumber) ? "manual" : registryNumber);
var folder = Path.Combine(_rootPath, safeFolder);
Directory.CreateDirectory(folder);
var baseName = MakeSafePathSegment(string.IsNullOrWhiteSpace(title) ? Path.GetFileNameWithoutExtension(sourceIdentity) : title);
if (string.IsNullOrWhiteSpace(baseName))
{
baseName = "document";
}
var fullPath = Path.Combine(folder, baseName + ".pdf");
if (!File.Exists(fullPath))
{
return fullPath;
}
var counter = 2;
while (true)
{
var candidate = Path.Combine(folder, $"{baseName}-{counter}.pdf");
if (!File.Exists(candidate))
{
return candidate;
}
counter++;
}
}
private static string MakeSafePathSegment(string value)
{
var invalid = Path.GetInvalidFileNameChars();
var cleaned = new string((value ?? string.Empty).Select(ch => invalid.Contains(ch) ? '_' : ch).ToArray()).Trim();
return string.IsNullOrWhiteSpace(cleaned) ? "file" : cleaned;
}
}