285 lines
14 KiB
C#
285 lines
14 KiB
C#
using Disco.Data.Repository;
|
|
using Disco.Models.Repository;
|
|
using Disco.Services.Logging;
|
|
using Disco.Services.Users;
|
|
using PdfSharp.Pdf;
|
|
using PdfSharp.Pdf.IO;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
namespace Disco.Services.Documents.AttachmentImport
|
|
{
|
|
public static class Importer
|
|
{
|
|
public static void Import(DiscoDataContext Database, string SessionId, string Filename)
|
|
{
|
|
var dataStoreUnassignedLocation = DataStore.CreateLocation(Database, "DocumentDropBox_Unassigned");
|
|
var dataStoreSessionPagesCacheLocation = DataStore.CreateLocation(Database, "Cache\\DocumentDropBox_SessionPages");
|
|
var documentTemplates = Database.DocumentTemplates.ToArray();
|
|
|
|
if (!File.Exists(Filename))
|
|
{
|
|
DocumentsLog.LogImportWarning(SessionId, $"File not found: {Filename}");
|
|
throw new FileNotFoundException("Document Not Found", Filename);
|
|
}
|
|
|
|
DocumentsLog.LogImportProgress(SessionId, 0, "Reading File");
|
|
|
|
List<ImportPage> pages = null;
|
|
List<ImportPage> assignedPages;
|
|
double progressInterval;
|
|
|
|
try
|
|
{
|
|
// Use Pdfium to Rasterize and Detect Pages
|
|
using (var importFileStream = new FileStream(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
|
|
{
|
|
using (var pdfiumDocument = PdfiumViewer.PdfDocument.Load(importFileStream))
|
|
{
|
|
progressInterval = 70D / pdfiumDocument.PageCount;
|
|
pages = new List<ImportPage>(pdfiumDocument.PageCount);
|
|
assignedPages = new List<ImportPage>(pdfiumDocument.PageCount);
|
|
|
|
// Rasterize and Detect Pages
|
|
for (int pageIndex = 0; pageIndex < pdfiumDocument.PageCount; pageIndex++)
|
|
{
|
|
var pageNumber = pageIndex + 1;
|
|
|
|
DocumentsLog.LogImportProgress(SessionId, (int)(pageIndex * progressInterval), $"Processing Page {pageNumber} of {pdfiumDocument.PageCount}");
|
|
DocumentsLog.LogImportPageStarting(SessionId, pageNumber);
|
|
|
|
var page = new ImportPage(Database, SessionId, pdfiumDocument, pageIndex);
|
|
pages.Add(page);
|
|
|
|
// Detect Image
|
|
if (page.DetectQRCode())
|
|
{
|
|
// Write session thumbnail
|
|
page.WriteThumbnailSessionCache();
|
|
DocumentsLog.LogImportPageImageUpdate(SessionId, pageNumber);
|
|
|
|
var identifier = page.Identifier;
|
|
DocumentsLog.LogImportPageDetected(SessionId, pageNumber, identifier.DocumentTemplate?.Id, identifier.DocumentTemplate?.Description, identifier.AttachmentType.ToString(), identifier.Target?.AttachmentReferenceId ?? identifier.TargetId, identifier.Target?.ToString() ?? $"Unknown [{identifier.TargetId}]");
|
|
}
|
|
else
|
|
{
|
|
// Write session thumbnail
|
|
page.WriteThumbnailSessionCache();
|
|
DocumentsLog.LogImportPageImageUpdate(SessionId, pageNumber);
|
|
|
|
page.WriteUndetectedImages();
|
|
DocumentsLog.LogImportPageUndetected(SessionId, pageNumber);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Use PdfSharp to Import and Build Documents
|
|
using (var importFileStream = new FileStream(Filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
|
|
{
|
|
using (var pdfSharpDocument = PdfReader.Open(importFileStream, PdfDocumentOpenMode.Import))
|
|
{
|
|
// Assign Pages
|
|
var documents = pages
|
|
.Where(p => p.IsValidAttachment)
|
|
.GroupBy(p => p.Identifier.DocumentGroupingId)
|
|
.ToList();
|
|
|
|
if (documents.Count > 0)
|
|
{
|
|
progressInterval = 20D / documents.Count;
|
|
|
|
foreach (var document in documents)
|
|
{
|
|
var documentPages = document.OrderBy(p => p.Identifier.PageIndex).ToList();
|
|
var documentPageFirst = documentPages.First();
|
|
|
|
DocumentsLog.LogImportProgress(SessionId, (int)(70D + (documents.IndexOf(document) * progressInterval)), $"Importing Documents {documents.IndexOf(document) + 1} of {documents.Count}");
|
|
|
|
using (MemoryStream msBuilder = new MemoryStream())
|
|
{
|
|
using (var pdfSharpDocumentOutput = new PdfDocument())
|
|
{
|
|
foreach (var documentPage in documentPages)
|
|
{
|
|
var pdfSharpImportPage = pdfSharpDocument.Pages[documentPage.PageIndex];
|
|
var importedPage = pdfSharpDocumentOutput.AddPage(pdfSharpImportPage);
|
|
|
|
importedPage.Rotate = documentPage.Rotation;
|
|
}
|
|
|
|
pdfSharpDocumentOutput.Save(msBuilder, false);
|
|
}
|
|
|
|
msBuilder.Position = 0;
|
|
using (var attachmentThumbnail = documentPageFirst.GetAttachmentThumbnail())
|
|
{
|
|
documentPageFirst.Identifier.ImportPdfAttachment(Database, msBuilder, attachmentThumbnail, documentPages.Select(p => p.Identifier).ToList());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Write Unassigned Pages
|
|
var unassignedPages = pages
|
|
.Where(p => !p.IsValidAttachment)
|
|
.ToList();
|
|
|
|
if (unassignedPages.Count > 0)
|
|
{
|
|
progressInterval = 10D / unassignedPages.Count;
|
|
|
|
foreach (var documentPage in unassignedPages)
|
|
{
|
|
DocumentsLog.LogImportProgress(SessionId, (int)(90 + (unassignedPages.IndexOf(documentPage) * progressInterval)), $"Processing Undetected Pages {unassignedPages.IndexOf(documentPage) + 1} of {unassignedPages.Count}");
|
|
|
|
using (var pdfSharpDocumentOutput = new PdfDocument())
|
|
{
|
|
var pdfSharpImportPage = pdfSharpDocument.Pages[documentPage.PageIndex];
|
|
pdfSharpDocumentOutput.AddPage(pdfSharpImportPage);
|
|
|
|
var filename = Path.Combine(dataStoreUnassignedLocation, $"{SessionId}_{documentPage.PageIndex + 1}.pdf");
|
|
|
|
pdfSharpDocumentOutput.Save(filename);
|
|
|
|
DocumentsLog.LogImportPageUndetectedStored(SessionId, documentPage.PageIndex + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
// Dispose of pages
|
|
if (pages != null && pages.Count != 0)
|
|
{
|
|
for (int i = 0; i < pages.Count; i++)
|
|
{
|
|
pages[i].Dispose();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static IAttachment ImportPdfAttachment(this DocumentUniqueIdentifier Identifier, DiscoDataContext Database, string PdfFilename)
|
|
{
|
|
return ImportPdfAttachment(Identifier, Database, PdfFilename, null);
|
|
}
|
|
|
|
public static IAttachment ImportPdfAttachment(this DocumentUniqueIdentifier Identifier, DiscoDataContext Database, string PdfFilename, Image Thumbnail)
|
|
{
|
|
using (var pdfStream = File.OpenRead(PdfFilename))
|
|
{
|
|
return ImportPdfAttachment(Identifier, Database, pdfStream, Thumbnail, new List<DocumentUniqueIdentifier>() { Identifier });
|
|
}
|
|
}
|
|
|
|
public static IAttachment ImportPdfAttachment(this DocumentUniqueIdentifier Identifier, DiscoDataContext Database, Stream PdfContent)
|
|
{
|
|
return ImportPdfAttachment(Identifier, Database, PdfContent, null, new List<DocumentUniqueIdentifier>() { Identifier });
|
|
}
|
|
|
|
public static IAttachment ImportPdfAttachment(this DocumentUniqueIdentifier Identifier, DiscoDataContext Database, Stream PdfContent, Image Thumbnail)
|
|
{
|
|
return ImportPdfAttachment(Identifier, Database, PdfContent, Thumbnail, new List<DocumentUniqueIdentifier>() { Identifier });
|
|
}
|
|
|
|
public static IAttachment ImportPdfAttachment(this DocumentUniqueIdentifier Identifier, DiscoDataContext Database, Stream PdfContent, Image Thumbnail, List<DocumentUniqueIdentifier> PageIdentifiers)
|
|
=> Identifier.ImportPdfAttachment(Database, PdfContent, Thumbnail, PageIdentifiers, null, null, null, null);
|
|
|
|
public static IAttachment ImportPdfAttachment(this DocumentUniqueIdentifier Identifier, DiscoDataContext Database, Stream PdfContent, Image Thumbnail, List<DocumentUniqueIdentifier> PageIdentifiers, DateTime? Timestamp, string HandlerId, string HandlerReferenceId, string HandlerData)
|
|
{
|
|
string filename;
|
|
string comments;
|
|
IAttachment attachment;
|
|
|
|
if (Identifier.DocumentTemplate == null)
|
|
{
|
|
if (Timestamp.HasValue)
|
|
{
|
|
filename = $"{Identifier.Target.AttachmentReferenceId.Replace('\\', '_')}_{Timestamp:yyyyMMdd-HHmmss}.pdf";
|
|
comments = $"Completed: {Timestamp:s}";
|
|
}
|
|
else
|
|
{
|
|
filename = $"{Identifier.Target.AttachmentReferenceId.Replace('\\', '_')}_{Identifier.TimeStamp:yyyyMMdd-HHmmss}.pdf";
|
|
comments = $"Uploaded: {Identifier.TimeStamp:s}";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Timestamp.HasValue)
|
|
{
|
|
filename = $"{Identifier.DocumentTemplateId}_{Timestamp:yyyyMMdd-HHmmss}.pdf";
|
|
comments = $"Generated: {Identifier.TimeStamp:s}; Completed: {Timestamp:s}";
|
|
}
|
|
else
|
|
{
|
|
filename = $"{Identifier.DocumentTemplateId}_{Identifier.TimeStamp:yyyyMMdd-HHmmss}.pdf";
|
|
comments = $"Generated: {Identifier.TimeStamp:s}";
|
|
}
|
|
}
|
|
|
|
User creatorUser = UserService.GetUser(Identifier.CreatorId, Database, false);
|
|
if (creatorUser == null)
|
|
{
|
|
// No Creator User (or Username invalid)
|
|
creatorUser = UserService.CurrentUser;
|
|
}
|
|
|
|
switch (Identifier.AttachmentType)
|
|
{
|
|
case AttachmentTypes.Device:
|
|
Device d = (Device)Identifier.Target;
|
|
attachment = d.CreateAttachment(Database, creatorUser, filename, Timestamp ?? DateTime.Now, DocumentTemplate.PdfMimeType, comments, PdfContent, Identifier.DocumentTemplate, Thumbnail, HandlerId, HandlerReferenceId, HandlerData);
|
|
break;
|
|
case AttachmentTypes.Job:
|
|
Job j = (Job)Identifier.Target;
|
|
attachment = j.CreateAttachment(Database, creatorUser, filename, Timestamp ?? DateTime.Now, DocumentTemplate.PdfMimeType, comments, PdfContent, Identifier.DocumentTemplate, Thumbnail, HandlerId, HandlerReferenceId, HandlerData);
|
|
break;
|
|
case AttachmentTypes.User:
|
|
User u = (User)Identifier.Target;
|
|
attachment = u.CreateAttachment(Database, creatorUser, filename, Timestamp ?? DateTime.Now, DocumentTemplate.PdfMimeType, comments, PdfContent, Identifier.DocumentTemplate, Thumbnail, HandlerId, HandlerReferenceId, HandlerData);
|
|
break;
|
|
default:
|
|
return null;
|
|
}
|
|
|
|
if (Identifier.DocumentTemplate != null)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(Identifier.DocumentTemplate.OnImportAttachmentExpression))
|
|
{
|
|
try
|
|
{
|
|
var expressionResult = Identifier.DocumentTemplate.EvaluateOnAttachmentImportExpression(attachment, Identifier.Target, Database, creatorUser, Identifier.TimeStamp, PageIdentifiers);
|
|
DocumentsLog.LogImportAttachmentExpressionEvaluated(Identifier.DocumentTemplate, Identifier.Target, attachment, expressionResult);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SystemLog.LogException("Document Importer - OnImportAttachmentExpression", ex);
|
|
}
|
|
}
|
|
|
|
if (Identifier.DocumentTemplate.OnImportUserFlagRules != null)
|
|
{
|
|
var rules = Identifier.DocumentTemplate.GetOnImportUserFlagRules();
|
|
|
|
foreach (var rule in rules)
|
|
{
|
|
rule.Apply(Database, Identifier.Target, creatorUser);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
return attachment;
|
|
}
|
|
}
|
|
}
|