scans

Co-authored-by: MaxchilKH <m.w.bohdanowicz@gmail.com>
This commit is contained in:
maxchil 2020-10-25 22:30:05 +01:00
parent 515f236632
commit 3d5fa43135
6 changed files with 61 additions and 9 deletions

View File

@ -1,6 +1,7 @@
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Mime;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using InternshipSystem.Api.Queries; using InternshipSystem.Api.Queries;
@ -100,7 +101,14 @@ namespace InternshipSystem.Api.Controllers
var document = internship.Documentation.First(d => d.Id == documentId); var document = internship.Documentation.First(d => d.Id == documentId);
document.Scan = new DocumentScan { File = memoryStream.ToArray() }; document.Scan = new DocumentScan
{
File = memoryStream.ToArray(),
Size = memoryStream.Length,
Filename = documentScan.FileName,
Mime = _fileValidator.GetFileMime(memoryStream.ToArray())
};
document.State = DocumentState.Submitted; document.State = DocumentState.Submitted;
await _context.SaveChangesAsync(cancellationToken); await _context.SaveChangesAsync(cancellationToken);
@ -110,7 +118,7 @@ namespace InternshipSystem.Api.Controllers
[HttpGet("{documentId}/scan")] [HttpGet("{documentId}/scan")]
[Authorize(Policy = Policies.RegisteredOnly)] [Authorize(Policy = Policies.RegisteredOnly)]
public async Task<ActionResult> GetDocumentScan(long documentId, [FromServices] User user, CancellationToken cancellationToken) public async Task<ActionResult> GetDocumentScan(long documentId, [FromQuery] string disposition, [FromServices] User user, CancellationToken cancellationToken)
{ {
var edition = await _context.Editions.FirstAsync(e => e.Id == user.EditionId, cancellationToken); var edition = await _context.Editions.FirstAsync(e => e.Id == user.EditionId, cancellationToken);
@ -128,8 +136,15 @@ namespace InternshipSystem.Api.Controllers
.FirstOrDefaultAsync(d => d.Id == documentId, cancellationToken); .FirstOrDefaultAsync(d => d.Id == documentId, cancellationToken);
var stream = new MemoryStream(document.Scan.File); var stream = new MemoryStream(document.Scan.File);
Response.Headers.Add("Content-Disposition", new ContentDisposition
{
Inline = disposition == "inline",
FileName = document.Scan.Filename,
Size = document.Scan.Size
}.ToString());
return File(stream, "application/pdf"); return File(stream, document.Scan.Mime);
} }
} }
} }

View File

@ -5,12 +5,15 @@ namespace InternshipSystem.Api.Service
{ {
public class FileValidator public class FileValidator
{ {
private readonly Dictionary<string, byte[]> validFileTypes; private readonly List<(string Mime, byte[] Signature)> validFileTypes;
public FileValidator() public FileValidator()
{ {
validFileTypes = new Dictionary<string, byte[]> { validFileTypes = new List<(string, byte[])> {
{ "pdf", new byte[] { 0x25, 0x50, 0x44, 0x46 } } ("application/pdf", new byte[] { 0x25, 0x50, 0x44, 0x46 }),
("image/jpeg", new byte[] { 0xFF, 0xD8, 0xFF, 0xDB }),
("image/jpeg", new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 }),
("image/jpeg", new byte[] { 0xFF, 0xD8, 0xFF, 0xE1 })
}; };
} }
@ -21,10 +24,14 @@ namespace InternshipSystem.Api.Service
private bool IsFileValidType(byte[] scan) private bool IsFileValidType(byte[] scan)
{ {
var validSignatures = validFileTypes.Values; return GetFileMime(scan) != null;
}
public string GetFileMime(byte[] scan)
{
var header = scan[..4]; var header = scan[..4];
return validSignatures.Any(sig => header.SequenceEqual(header)); return validFileTypes.FirstOrDefault(sig => sig.Signature.SequenceEqual(header)).Mime;
} }
} }
} }

View File

@ -16,6 +16,9 @@ namespace InternshipSystem.Core
{ {
public long DocumentId { get; set; } public long DocumentId { get; set; }
public Document Document { get; set; } public Document Document { get; set; }
public long Size { get; set; }
public string Filename { get; set; }
public string Mime { get; set; }
public byte[] File { get; set; } public byte[] File { get; set; }
} }
} }

View File

@ -10,7 +10,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace InternshipSystem.Repository.Migrations namespace InternshipSystem.Repository.Migrations
{ {
[DbContext(typeof(InternshipDbContext))] [DbContext(typeof(InternshipDbContext))]
[Migration("20201018000658_Init")] [Migration("20201025211622_Init")]
partial class Init partial class Init
{ {
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -137,6 +137,18 @@ namespace InternshipSystem.Repository.Migrations
.HasColumnName("file") .HasColumnName("file")
.HasColumnType("bytea"); .HasColumnType("bytea");
b.Property<string>("Filename")
.HasColumnName("filename")
.HasColumnType("text");
b.Property<string>("Mime")
.HasColumnName("mime")
.HasColumnType("text");
b.Property<long>("Size")
.HasColumnName("size")
.HasColumnType("bigint");
b.HasKey("DocumentId") b.HasKey("DocumentId")
.HasName("pk_document_scan"); .HasName("pk_document_scan");

View File

@ -344,6 +344,9 @@ namespace InternshipSystem.Repository.Migrations
columns: table => new columns: table => new
{ {
document_id = table.Column<long>(nullable: false), document_id = table.Column<long>(nullable: false),
size = table.Column<long>(nullable: false),
filename = table.Column<string>(nullable: true),
mime = table.Column<string>(nullable: true),
file = table.Column<byte[]>(nullable: true) file = table.Column<byte[]>(nullable: true)
}, },
constraints: table => constraints: table =>

View File

@ -135,6 +135,18 @@ namespace InternshipSystem.Repository.Migrations
.HasColumnName("file") .HasColumnName("file")
.HasColumnType("bytea"); .HasColumnType("bytea");
b.Property<string>("Filename")
.HasColumnName("filename")
.HasColumnType("text");
b.Property<string>("Mime")
.HasColumnName("mime")
.HasColumnType("text");
b.Property<long>("Size")
.HasColumnName("size")
.HasColumnType("bigint");
b.HasKey("DocumentId") b.HasKey("DocumentId")
.HasName("pk_document_scan"); .HasName("pk_document_scan");