Add support for generating result PDFs
Introduced the `ResultFilePath` property in the `ZugferdInvoice` model to store the path of generated result PDFs. Added a new service, `PdfResultPackageService`, to create result PDFs by converting the original PDF to PDF/A-3b format and attaching a report file. Updated `Upload.cshtml` and `Upload.cshtml.cs` to handle and display the `ResultFilePath`. Created a migration to add the `ResultFilePath` column to the database. Updated `Program.cs` to register the new service and added configuration sections in `appsettings.json` for input and output directories. Enhanced error handling and logging for better traceability.
This commit is contained in:
93
DXApp.TemplateKitProject/Services/PdfResultPackageService.cs
Normal file
93
DXApp.TemplateKitProject/Services/PdfResultPackageService.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using DevExpress.Pdf;
|
||||
using DXApp.TemplateKitProject.Models;
|
||||
|
||||
namespace DXApp.TemplateKitProject.Services;
|
||||
|
||||
public class PdfResultPackageService(
|
||||
IConfiguration configuration,
|
||||
ILogger<PdfResultPackageService> logger)
|
||||
{
|
||||
public async Task<string?> CreateResultPackageAsync(
|
||||
byte[] originalPdfBytes,
|
||||
string originalFileName,
|
||||
ZugferdInvoice invoice)
|
||||
{
|
||||
// 1. Bericht-PDF suchen
|
||||
var reportPath = FindReportFile(originalFileName);
|
||||
if (reportPath is null)
|
||||
{
|
||||
logger.LogWarning(
|
||||
"Kein Ergebnisbericht gefunden für '{FileName}'.", originalFileName);
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.LogInformation(
|
||||
"Ergebnisbericht gefunden: '{ReportPath}'.", reportPath);
|
||||
|
||||
// 2. Ausgabepfad bestimmen
|
||||
var outputDir = configuration["PdfResults:OutputDirectory"]
|
||||
?? Path.Combine(Path.GetTempPath(), "PdfResults");
|
||||
Directory.CreateDirectory(outputDir);
|
||||
|
||||
var baseName = Path.GetFileNameWithoutExtension(originalFileName);
|
||||
var outputPath = Path.Combine(outputDir, $"{baseName}_result.pdf");
|
||||
|
||||
// 3. Original auf PDF/A-3b hochstufen + Bericht anhängen
|
||||
await Task.Run(() =>
|
||||
{
|
||||
// Original in MemoryStream laden
|
||||
using var inputStream = new MemoryStream(originalPdfBytes);
|
||||
using var outputStream = new MemoryStream();
|
||||
|
||||
// PDF/A-3b Konvertierung
|
||||
var converter = new PdfDocumentConverter(inputStream);
|
||||
converter.Convert(PdfCompatibility.PdfA3b);
|
||||
|
||||
// Konvertiertes PDF in MemoryStream speichern
|
||||
using var convertedStream = new MemoryStream();
|
||||
converter.SaveDocument(convertedStream);
|
||||
convertedStream.Position = 0;
|
||||
|
||||
// Bericht als Anhang einbetten
|
||||
using var processor = new PdfDocumentProcessor();
|
||||
processor.LoadDocument(convertedStream);
|
||||
|
||||
processor.AttachFile(new PdfFileAttachment
|
||||
{
|
||||
FileName = Path.GetFileName(reportPath),
|
||||
Description = "Ergebnisbericht",
|
||||
MimeType = "application/pdf",
|
||||
Relationship = PdfAssociatedFileRelationship.Supplement,
|
||||
CreationDate = DateTime.Now,
|
||||
Data = File.ReadAllBytes(reportPath)
|
||||
});
|
||||
|
||||
// Speichern
|
||||
processor.SaveDocument(outputPath);
|
||||
});
|
||||
|
||||
logger.LogInformation(
|
||||
"Result-PDF gespeichert: '{OutputPath}'.", outputPath);
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
private string? FindReportFile(string originalFileName)
|
||||
{
|
||||
var inputDir = configuration["PdfResultReports:InputDirectory"]
|
||||
?? Path.Combine(Path.GetTempPath(), "PdfResultReports");
|
||||
|
||||
if (!Directory.Exists(inputDir))
|
||||
{
|
||||
logger.LogWarning("Berichtsverzeichnis nicht gefunden: '{Dir}'.", inputDir);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Konvention Option A: {originalname}_report.pdf
|
||||
var baseName = Path.GetFileNameWithoutExtension(originalFileName);
|
||||
var reportName = $"{baseName}_report.pdf";
|
||||
var reportPath = Path.Combine(inputDir, reportName);
|
||||
|
||||
return File.Exists(reportPath) ? reportPath : null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user