100 lines
3.4 KiB
C#
100 lines
3.4 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.");
|
|
var configuredPath = Environment.ExpandEnvironmentVariables(options.PdfStoragePath ?? string.Empty).Trim();
|
|
if (string.IsNullOrWhiteSpace(configuredPath))
|
|
{
|
|
configuredPath = "PdfStore";
|
|
}
|
|
|
|
_rootPath = Path.IsPathRooted(configuredPath)
|
|
? configuredPath
|
|
: Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, configuredPath));
|
|
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;
|
|
}
|
|
}
|