Compare commits
3 Commits
9adc9ac4ed
...
a087baa089
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a087baa089 | ||
|
|
98226f239b | ||
|
|
1144c45826 |
@@ -38,7 +38,7 @@ public class PdfAttachmentExtractorService(
|
|||||||
};
|
};
|
||||||
result.PdfAWarning = compatibility == PdfACompatibility.None;
|
result.PdfAWarning = compatibility == PdfACompatibility.None;
|
||||||
|
|
||||||
logger.LogInformation(
|
logger.LogDebug(
|
||||||
"PDF '{FileName}': Konformität = {Level}",
|
"PDF '{FileName}': Konformität = {Level}",
|
||||||
sourceFileName, result.PdfALevel);
|
sourceFileName, result.PdfALevel);
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ public class PdfAttachmentExtractorService(
|
|||||||
{
|
{
|
||||||
result.ZugferdGuidelineId = ExtractGuidelineId(xmpData);
|
result.ZugferdGuidelineId = ExtractGuidelineId(xmpData);
|
||||||
if (!string.IsNullOrEmpty(result.ZugferdGuidelineId))
|
if (!string.IsNullOrEmpty(result.ZugferdGuidelineId))
|
||||||
logger.LogInformation(
|
logger.LogDebug(
|
||||||
"PDF '{FileName}': Guideline-ID = {GuidelineId}",
|
"PDF '{FileName}': Guideline-ID = {GuidelineId}",
|
||||||
sourceFileName, result.ZugferdGuidelineId);
|
sourceFileName, result.ZugferdGuidelineId);
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ public class PdfAttachmentExtractorService(
|
|||||||
|
|
||||||
var isZugferd = IsZugferdXml(attachment.FileName);
|
var isZugferd = IsZugferdXml(attachment.FileName);
|
||||||
|
|
||||||
logger.LogInformation(
|
logger.LogDebug(
|
||||||
" → Gespeichert: '{FileName}' ({Bytes} Bytes){Zugferd}",
|
" → Gespeichert: '{FileName}' ({Bytes} Bytes){Zugferd}",
|
||||||
safeFileName, data.Length,
|
safeFileName, data.Length,
|
||||||
isZugferd ? " [ZUGFeRD/Factur-X XML]" : string.Empty);
|
isZugferd ? " [ZUGFeRD/Factur-X XML]" : string.Empty);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class PdfResultPackageService(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation(
|
logger.LogDebug(
|
||||||
"Ergebnisbericht gefunden: '{ReportPath}'.", reportPath);
|
"Ergebnisbericht gefunden: '{ReportPath}'.", reportPath);
|
||||||
|
|
||||||
// 2. Ausgabepfad bestimmen
|
// 2. Ausgabepfad bestimmen
|
||||||
@@ -35,20 +35,28 @@ public class PdfResultPackageService(
|
|||||||
// 3. Original auf PDF/A-3b hochstufen + Bericht anhängen
|
// 3. Original auf PDF/A-3b hochstufen + Bericht anhängen
|
||||||
await Task.Run(() =>
|
await Task.Run(() =>
|
||||||
{
|
{
|
||||||
// Original in MemoryStream laden
|
|
||||||
using var inputStream = new MemoryStream(originalPdfBytes);
|
using var inputStream = new MemoryStream(originalPdfBytes);
|
||||||
using var outputStream = new MemoryStream();
|
|
||||||
|
|
||||||
// PDF/A-3b Konvertierung
|
// Schritt 1: PDF/A-3b Konvertierung
|
||||||
var converter = new PdfDocumentConverter(inputStream);
|
PdfDocumentConverter converter;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
converter = new PdfDocumentConverter(inputStream);
|
||||||
converter.Convert(PdfCompatibility.PdfA3b);
|
converter.Convert(PdfCompatibility.PdfA3b);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Konvertierung nach PDF/A-3b fehlgeschlagen. " +
|
||||||
|
"Die Originaldatei ist möglicherweise beschädigt oder nicht konvertierbar.", ex);
|
||||||
|
}
|
||||||
|
|
||||||
// Konvertiertes PDF in MemoryStream speichern
|
// Schritt 2: Konvertiertes PDF puffern
|
||||||
using var convertedStream = new MemoryStream();
|
using var convertedStream = new MemoryStream();
|
||||||
converter.SaveDocument(convertedStream);
|
converter.SaveDocument(convertedStream);
|
||||||
convertedStream.Position = 0;
|
convertedStream.Position = 0;
|
||||||
|
|
||||||
// Bericht als Anhang einbetten
|
// Schritt 3: Anhang einbetten
|
||||||
using var processor = new PdfDocumentProcessor();
|
using var processor = new PdfDocumentProcessor();
|
||||||
processor.LoadDocument(convertedStream);
|
processor.LoadDocument(convertedStream);
|
||||||
|
|
||||||
@@ -62,8 +70,65 @@ public class PdfResultPackageService(
|
|||||||
Data = File.ReadAllBytes(reportPath)
|
Data = File.ReadAllBytes(reportPath)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Speichern
|
// Schritt 4: Stempel auf Seite 1 zeichnen
|
||||||
|
var firstPage = processor.Document.Pages[0];
|
||||||
|
using (var graphics = processor.CreateGraphicsWorldSystem())
|
||||||
|
{
|
||||||
|
// Stempel-Position: oben rechts
|
||||||
|
// Welt-Koordinaten: Ursprung oben links, X nach rechts, Y nach unten
|
||||||
|
var stampX = (float)firstPage.CropBox.Width - 200;
|
||||||
|
var stampY = 20f;
|
||||||
|
var stampWidth = 175f;
|
||||||
|
var stampHeight = 50f;
|
||||||
|
|
||||||
|
// Hintergrund weiß
|
||||||
|
using var whiteBrush = new DevExpress.Drawing.DXSolidBrush(
|
||||||
|
System.Drawing.Color.White);
|
||||||
|
graphics.FillRectangle(whiteBrush,
|
||||||
|
new System.Drawing.RectangleF(stampX, stampY, stampWidth, stampHeight));
|
||||||
|
|
||||||
|
// Rahmen grün
|
||||||
|
using var greenPen = new DevExpress.Drawing.DXPen(
|
||||||
|
System.Drawing.Color.Green, 1.5f);
|
||||||
|
graphics.DrawRectangle(greenPen,
|
||||||
|
new System.Drawing.RectangleF(stampX, stampY, stampWidth, stampHeight));
|
||||||
|
|
||||||
|
// Text Zeile 1: VERARBEITET
|
||||||
|
using var greenBrush = new DevExpress.Drawing.DXSolidBrush(
|
||||||
|
System.Drawing.Color.Green);
|
||||||
|
var fontBold = new DevExpress.Drawing.DXFont(
|
||||||
|
"Arial", 11, DevExpress.Drawing.DXFontStyle.Bold);
|
||||||
|
graphics.DrawString(
|
||||||
|
"✔ VERARBEITET",
|
||||||
|
fontBold,
|
||||||
|
greenBrush,
|
||||||
|
new System.Drawing.PointF(stampX + 8, stampY + 6));
|
||||||
|
|
||||||
|
// Text Zeile 2: Datum/Uhrzeit
|
||||||
|
using var grayBrush = new DevExpress.Drawing.DXSolidBrush(
|
||||||
|
System.Drawing.Color.DimGray);
|
||||||
|
var fontNormal = new DevExpress.Drawing.DXFont("Arial", 9);
|
||||||
|
graphics.DrawString(
|
||||||
|
DateTime.Now.ToString("dd.MM.yyyy HH:mm"),
|
||||||
|
fontNormal,
|
||||||
|
grayBrush,
|
||||||
|
new System.Drawing.PointF(stampX + 8, stampY + 28));
|
||||||
|
|
||||||
|
graphics.AddToPageForeground(
|
||||||
|
processor.Document.Pages[0], 96, 96);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schritt 4: Speichern
|
||||||
|
try
|
||||||
|
{
|
||||||
processor.SaveDocument(outputPath);
|
processor.SaveDocument(outputPath);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"Result-PDF konnte nicht gespeichert werden unter '{outputPath}'. " +
|
||||||
|
"Prüfe ob das Verzeichnis existiert und beschreibbar ist.", ex);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.LogInformation(
|
logger.LogInformation(
|
||||||
|
|||||||
Reference in New Issue
Block a user