using Microsoft.AspNetCore.Hosting;
using NexusReader.Application.Abstractions.Services;
namespace NexusReader.Infrastructure.Services;
///
/// Infrastructure implementation of book storage using local filesystem.
/// All paths returned are relative to the web root.
///
public class BookStorageService : IBookStorageService
{
private readonly IWebHostEnvironment _environment;
public BookStorageService(IWebHostEnvironment environment)
{
_environment = environment;
}
public async Task SaveEbookAsync(byte[] data, string fileName)
{
using var stream = new MemoryStream(data);
return await SaveEbookAsync(stream, fileName);
}
public async Task SaveEbookAsync(Stream data, string fileName)
{
var uploadsFolder = Path.Combine(_environment.WebRootPath, "uploads");
EnsureDirectoryExists(uploadsFolder);
var uniqueFileName = $"{Guid.NewGuid()}_{fileName}";
var filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await data.CopyToAsync(fileStream);
}
return Path.Combine("uploads", uniqueFileName);
}
public async Task SaveCoverAsync(byte[] data, string fileName)
{
if (data == null || data.Length == 0) return null;
using var stream = new MemoryStream(data);
return await SaveCoverAsync(stream, fileName);
}
public async Task SaveCoverAsync(Stream data, string fileName)
{
var coversFolder = Path.Combine(_environment.WebRootPath, "covers");
EnsureDirectoryExists(coversFolder);
var uniqueFileName = $"{Guid.NewGuid()}_{fileName}";
var filePath = Path.Combine(coversFolder, uniqueFileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await data.CopyToAsync(fileStream);
}
return Path.Combine("covers", uniqueFileName);
}
private void EnsureDirectoryExists(string path)
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}
}