| [ExcludeFromCodeCoverage] | [ExcludeFromCodeCoverage] | ||||
| public static class FileExtensions | public static class FileExtensions | ||||
| { | { | ||||
| public static IQueryable<FileEntity> FilterByExtension(this IQueryable<FileEntity> query, string[]? values) | |||||
| public static List<FileFilterReturnDto> FilterByExtension(this List<FileFilterReturnDto> query, string[]? values) | |||||
| { | { | ||||
| if (values == null || values.Length == 0) | if (values == null || values.Length == 0) | ||||
| return query; | return query; | ||||
| return query.Where(n => values.Contains(n.Extension)); | |||||
| return query.Where(n => values.Contains(n.file_type)).ToList(); | |||||
| } | } | ||||
| public static IQueryable<FileEntity> FilterByCategory(this IQueryable<FileEntity> query, string[]? values) | |||||
| public static List<FileFilterReturnDto> FilterByCategory(this List<FileFilterReturnDto> query, string[]? values) | |||||
| { | { | ||||
| if (values == null || values.Length == 0) | if (values == null || values.Length == 0) | ||||
| return query; | return query; | ||||
| return query.Where(n => values.Contains(n.Category.Name)); | |||||
| return query.Where(n => values.Contains(n.Category.CategoryName)).ToList(); | |||||
| } | } | ||||
| public static IQueryable<FileEntity> FilterByTags(this IQueryable<FileEntity> query, string[]? values) | |||||
| public static List<FileFilterReturnDto> FilterByTags(this List<FileFilterReturnDto> query, string[]? values) | |||||
| { | { | ||||
| if (values == null || values.Length == 0) | if (values == null || values.Length == 0) | ||||
| return query; | return query; | ||||
| //return query.Where(n => values.Any(x => n.Tags.Any(y => y.Name == x))); | //return query.Where(n => values.Any(x => n.Tags.Any(y => y.Name == x))); | ||||
| return query.Where(n => n.Tags.Any(x => values.Contains(x.Name))); | |||||
| return query.Where(n => n.Tags.Any(x => values.Contains(x.TagName))).ToList(); | |||||
| } | } | ||||
| public static IQueryable<FileEntity> FilterFiles(this IQueryable<FileEntity> query, FileFilter filters) | |||||
| public static List<FileFilterReturnDto> FilterFiles(this List<FileFilterReturnDto> query, FileFilter filters) | |||||
| { | { | ||||
| return query | return query | ||||
| .FilterByCategory(filters.Categories) | .FilterByCategory(filters.Categories) |
| using Microsoft.AspNetCore.Http; | using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.Extensions.Configuration; | using Microsoft.Extensions.Configuration; | ||||
| using System.Data.SqlClient; | using System.Data.SqlClient; | ||||
| using static System.Net.Mime.MediaTypeNames; | |||||
| namespace Diligent.WebAPI.Business.Services | namespace Diligent.WebAPI.Business.Services | ||||
| { | { | ||||
| return files.ToList(); | return files.ToList(); | ||||
| } | } | ||||
| public async Task UploadDocument(IFormFile file) | |||||
| public async Task<DocumentReadDTO> UploadDocument(IFormFile file) | |||||
| { | { | ||||
| using var connection = new SqlConnection(_configuration.GetConnectionString("WebApi")); | using var connection = new SqlConnection(_configuration.GetConnectionString("WebApi")); | ||||
| var ms = new MemoryStream(); | var ms = new MemoryStream(); | ||||
| file.CopyTo(ms); | file.CopyTo(ms); | ||||
| var fileBytes = ms.ToArray(); | var fileBytes = ms.ToArray(); | ||||
| await connection.ExecuteAsync("insert into dbo.DocumentOrganizerDocStore (file_stream,name) values(@fileBytes,'neki2.txt')", | |||||
| new { fileBytes = fileBytes }); | |||||
| string fileName = string.Format(@"{0}" + $"{Path.GetExtension(file.FileName)}", DateTime.Now.Ticks); | |||||
| await connection.ExecuteAsync("insert into dbo.DocumentOrganizerDocStore (file_stream,name) values(@fileBytes,@fileName)", | |||||
| new { fileBytes = fileBytes, fileName = fileName }); | |||||
| var fileByName = await connection.QueryFirstAsync<DocumentReadDTO>("select * from dbo.DocumentOrganizerDocStore where name=@fileName", | |||||
| new { fileName = fileName }); | |||||
| return fileByName; | |||||
| } | } | ||||
| } | } | ||||
| } | } |
| using Azure.Core; | using Azure.Core; | ||||
| using Dapper; | |||||
| using Diligent.WebAPI.Contracts.DTOs.Categories; | |||||
| using Diligent.WebAPI.Contracts.DTOs.Document; | |||||
| using Diligent.WebAPI.Contracts.DTOs.File; | using Diligent.WebAPI.Contracts.DTOs.File; | ||||
| using Diligent.WebAPI.Contracts.DTOs.Files; | using Diligent.WebAPI.Contracts.DTOs.Files; | ||||
| using Diligent.WebAPI.Contracts.DTOs.Tags; | |||||
| using Microsoft.Extensions.Configuration; | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Data.SqlClient; | |||||
| using System.Linq; | using System.Linq; | ||||
| using System.Text; | using System.Text; | ||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
| using static System.Net.Mime.MediaTypeNames; | |||||
| namespace Diligent.WebAPI.Business.Services | namespace Diligent.WebAPI.Business.Services | ||||
| { | { | ||||
| private readonly ILogger<FileEntityService> _logger; | private readonly ILogger<FileEntityService> _logger; | ||||
| private readonly DatabaseContext _context; | private readonly DatabaseContext _context; | ||||
| private readonly IMapper _mapper; | private readonly IMapper _mapper; | ||||
| private readonly IConfiguration _configuration; | |||||
| public FileEntityService(DatabaseContext context, ILogger<FileEntityService> logger, IMapper mapper) | |||||
| public FileEntityService(DatabaseContext context, ILogger<FileEntityService> logger, IMapper mapper, IConfiguration configuration) | |||||
| { | { | ||||
| _context = context; | _context = context; | ||||
| _logger = logger; | _logger = logger; | ||||
| _mapper = mapper; | _mapper = mapper; | ||||
| _configuration = configuration; | |||||
| } | } | ||||
| public async Task<List<FileEntityResponse>> GetAllAsync() => | public async Task<List<FileEntityResponse>> GetAllAsync() => | ||||
| public async Task<object> GetAllFiltered(FileFilter filters) | public async Task<object> GetAllFiltered(FileFilter filters) | ||||
| { | { | ||||
| var filtered = await _context.Files | |||||
| .Include(n => n.Tags) | |||||
| .Include(n => n.Category) | |||||
| .FilterFiles(filters) | |||||
| .ToListAsync(); | |||||
| using var connection = new SqlConnection(_configuration.GetConnectionString("WebApi")); | |||||
| var files = await connection.QueryAsync<FileFilterReturnDto, TagResponse, CategoryResponse, FileFilterReturnDto>("SELECT Files.Id as FileId, stream_id, DocumentOrganizerDocStore.name as FileName, file_stream, file_type, cached_file_size, Tags.Id as TagId, Tags.Name as TagName, Categories.Id as CategoryId, Categories.Name as CategoryName FROM Files inner join FileEntityTag on Files.Id = FileEntityTag.FilesId inner join Tags on FileEntityTag.TagsId = Tags.Id inner join DocumentOrganizerDocStore on DocumentOrganizerDocStore.stream_id = Files.DocumentId inner join Categories on Files.CategoryId = Categories.Id;", (file, tag, category) => | |||||
| { | |||||
| file.Tags.Add(tag); | |||||
| file.Category = category; | |||||
| return file; | |||||
| }, splitOn: "TagId, CategoryId"); | |||||
| var filesList = files.ToList(); | |||||
| var filtered = filesList | |||||
| .FilterFiles(filters); | |||||
| return new | return new | ||||
| { | { | ||||
| Data = filtered.ApplyPagging(filters) | Data = filtered.ApplyPagging(filters) | ||||
| .Select(n => new { n.Id, n.Name, n.Size, n.Extension}), | |||||
| .Select(n => new { n.stream_id, n.FileName, n.cached_file_size, n.file_type }), | |||||
| Total = filtered.Count | Total = filtered.Count | ||||
| }; | }; | ||||
| } | } |
| { | { | ||||
| Task<List<DocumentReadDTO>> GetAllDocuments(); | Task<List<DocumentReadDTO>> GetAllDocuments(); | ||||
| Task<List<DocumentReadDTO>> GetDocumentsByText(string text); | Task<List<DocumentReadDTO>> GetDocumentsByText(string text); | ||||
| Task UploadDocument(IFormFile file); | |||||
| Task<DocumentReadDTO> UploadDocument(IFormFile file); | |||||
| } | } | ||||
| } | } |
| using Diligent.WebAPI.Contracts.DTOs.Categories; | |||||
| using Dapper; | |||||
| using Diligent.WebAPI.Contracts.DTOs.Categories; | |||||
| using Diligent.WebAPI.Contracts.DTOs.Files; | using Diligent.WebAPI.Contracts.DTOs.Files; | ||||
| using Diligent.WebAPI.Contracts.DTOs.Tags; | using Diligent.WebAPI.Contracts.DTOs.Tags; | ||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||
| using Microsoft.Extensions.Configuration; | |||||
| using System.Data.SqlClient; | |||||
| using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database; | |||||
| namespace Diligent.WebAPI.Business.Services | namespace Diligent.WebAPI.Business.Services | ||||
| { | { | ||||
| { | { | ||||
| private readonly DatabaseContext _databaseContext; | private readonly DatabaseContext _databaseContext; | ||||
| private readonly IMapper _mapper; | private readonly IMapper _mapper; | ||||
| private readonly IConfiguration _configuration; | |||||
| public TagService(DatabaseContext databaseContext, IMapper mapper) | |||||
| public TagService(DatabaseContext databaseContext, IMapper mapper, IConfiguration configuration) | |||||
| { | { | ||||
| _databaseContext = databaseContext; | _databaseContext = databaseContext; | ||||
| _mapper = mapper; | _mapper = mapper; | ||||
| _configuration = configuration; | |||||
| } | } | ||||
| public async Task<FileFiltersReturnDTO> GetFilters() | public async Task<FileFiltersReturnDTO> GetFilters() | ||||
| { | { | ||||
| var categories = await _databaseContext.Categories.ToArrayAsync(); | var categories = await _databaseContext.Categories.ToArrayAsync(); | ||||
| var tags = await _databaseContext.Tags.ToArrayAsync(); | var tags = await _databaseContext.Tags.ToArrayAsync(); | ||||
| var extensions = await _databaseContext.Files | |||||
| .Select(m => m.Extension).Distinct().ToArrayAsync(); | |||||
| using var connection = new SqlConnection(_configuration.GetConnectionString("WebApi")); | |||||
| var files = await connection.QueryAsync<FileFilterReturnDto>("SELECT * FROM Files inner join DocumentOrganizerDocStore on DocumentOrganizerDocStore.stream_id = Files.DocumentId;"); | |||||
| var extensionsArray = files.Select(x => x.file_type).ToArray(); | |||||
| return new FileFiltersReturnDTO | return new FileFiltersReturnDTO | ||||
| { | { | ||||
| Categories = categories, | Categories = categories, | ||||
| Tags = tags, | Tags = tags, | ||||
| Extensions = extensions | |||||
| Extensions = extensionsArray | |||||
| }; | }; | ||||
| } | } | ||||
| { | { | ||||
| public class CategoryResponse | public class CategoryResponse | ||||
| { | { | ||||
| public int Id { get; set; } | |||||
| public int CategoryId { get; set; } | |||||
| public string Name { get; set; } | |||||
| public string CategoryName { get; set; } | |||||
| public List<FileEntityResponse> Files { get; set; } | public List<FileEntityResponse> Files { get; set; } | ||||
| } | } |
| using Diligent.WebAPI.Contracts.DTOs.Categories; | |||||
| using Diligent.WebAPI.Contracts.DTOs.Tags; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| using System.Threading.Tasks; | |||||
| namespace Diligent.WebAPI.Contracts.DTOs.Files | |||||
| { | |||||
| public class FileFilterReturnDto | |||||
| { | |||||
| public Guid stream_id { get; set; } | |||||
| public string FileName { get; set; } | |||||
| public string file_type { get; set; } | |||||
| public int cached_file_size { get; set; } | |||||
| public List<TagResponse> Tags { get; set; } = new(); | |||||
| public CategoryResponse Category { get; set; } | |||||
| } | |||||
| } |
| { | { | ||||
| public class TagResponse | public class TagResponse | ||||
| { | { | ||||
| public int Id { get; set; } | |||||
| public int TagId { get; set; } | |||||
| public string Name { get; set; } | |||||
| public string TagName { get; set; } | |||||
| } | } | ||||
| } | } |
| { | { | ||||
| public int Id { get; set; } | public int Id { get; set; } | ||||
| public string Name { get; set; } | |||||
| public long Size { get; set; } | |||||
| public string Extension { get; set; } | |||||
| public Guid DocumentId { get; set; } | |||||
| [ForeignKey(nameof(Category))] | [ForeignKey(nameof(Category))] | ||||
| public int CategoryId { get; set; } | public int CategoryId { get; set; } |
| using System; | |||||
| using Microsoft.EntityFrameworkCore.Migrations; | |||||
| #nullable disable | |||||
| namespace Diligent.WebAPI.Data.Migrations | |||||
| { | |||||
| public partial class FileEntityChanged : Migration | |||||
| { | |||||
| protected override void Up(MigrationBuilder migrationBuilder) | |||||
| { | |||||
| migrationBuilder.DropColumn( | |||||
| name: "Extension", | |||||
| table: "Files"); | |||||
| migrationBuilder.DropColumn( | |||||
| name: "Name", | |||||
| table: "Files"); | |||||
| migrationBuilder.DropColumn( | |||||
| name: "Size", | |||||
| table: "Files"); | |||||
| migrationBuilder.AddColumn<Guid>( | |||||
| name: "DocumentId", | |||||
| table: "Files", | |||||
| type: "uniqueidentifier", | |||||
| nullable: false, | |||||
| defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); | |||||
| } | |||||
| protected override void Down(MigrationBuilder migrationBuilder) | |||||
| { | |||||
| migrationBuilder.DropColumn( | |||||
| name: "DocumentId", | |||||
| table: "Files"); | |||||
| migrationBuilder.AddColumn<string>( | |||||
| name: "Extension", | |||||
| table: "Files", | |||||
| type: "nvarchar(max)", | |||||
| nullable: false, | |||||
| defaultValue: ""); | |||||
| migrationBuilder.AddColumn<string>( | |||||
| name: "Name", | |||||
| table: "Files", | |||||
| type: "nvarchar(max)", | |||||
| nullable: false, | |||||
| defaultValue: ""); | |||||
| migrationBuilder.AddColumn<long>( | |||||
| name: "Size", | |||||
| table: "Files", | |||||
| type: "bigint", | |||||
| nullable: false, | |||||
| defaultValue: 0L); | |||||
| } | |||||
| } | |||||
| } |
| b.Property<int>("CategoryId") | b.Property<int>("CategoryId") | ||||
| .HasColumnType("int"); | .HasColumnType("int"); | ||||
| b.Property<string>("Extension") | |||||
| .IsRequired() | |||||
| .HasColumnType("nvarchar(max)"); | |||||
| b.Property<string>("Name") | |||||
| .IsRequired() | |||||
| .HasColumnType("nvarchar(max)"); | |||||
| b.Property<long>("Size") | |||||
| .HasColumnType("bigint"); | |||||
| b.Property<Guid>("DocumentId") | |||||
| .HasColumnType("uniqueidentifier"); | |||||
| b.HasKey("Id"); | b.HasKey("Id"); | ||||
| private readonly ICategoryService _categoryService; | private readonly ICategoryService _categoryService; | ||||
| private readonly ITagService _tagService; | private readonly ITagService _tagService; | ||||
| private readonly IFileEntityService _fileEntityService; | private readonly IFileEntityService _fileEntityService; | ||||
| private readonly IDocumentService _documentService; | |||||
| private readonly Microsoft.AspNetCore.Hosting.IHostingEnvironment _hostingEnvironment; | private readonly Microsoft.AspNetCore.Hosting.IHostingEnvironment _hostingEnvironment; | ||||
| public FilesController(Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment, IFileEntityService fileEntityService, ICategoryService categoryService, ITagService tagService) | |||||
| public FilesController(Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment, IFileEntityService fileEntityService, ICategoryService categoryService, ITagService tagService, IDocumentService documentService) | |||||
| { | { | ||||
| _hostingEnvironment = hostingEnvironment; | _hostingEnvironment = hostingEnvironment; | ||||
| _fileEntityService = fileEntityService; | _fileEntityService = fileEntityService; | ||||
| _categoryService = categoryService; | _categoryService = categoryService; | ||||
| _tagService = tagService; | _tagService = tagService; | ||||
| _documentService = documentService; | |||||
| } | } | ||||
| [HttpGet] | [HttpGet] | ||||
| foreach (var id in request.TagsIds) | foreach (var id in request.TagsIds) | ||||
| tags.Add(await _tagService.GetTagEntityById(id)); | tags.Add(await _tagService.GetTagEntityById(id)); | ||||
| var file = await _documentService.UploadDocument(request.FileToUpload); | |||||
| await _fileEntityService.UploadPdfAsync(new FileEntity { CategoryId = request.CategoryId, Category = category, Tags = tags, Name = filePath, Extension = "pdf", Size = 100}); | |||||
| await _fileEntityService.UploadPdfAsync(new FileEntity { CategoryId = request.CategoryId, DocumentId = file.stream_id, Category = category, Tags = tags}); | |||||
| return Ok(); | return Ok(); | ||||
| } | } | ||||
| } | } |