我很难理解如何从PdfDocument中获取内容。我从之前的问题中了解到PdfDocument刷新内容以优化处理大型文档。如果我的函数返回一个新的PdfDocument,我如何让字节[]传递给我的其他函数?
即使使用PdfDocument. GetReader()-我似乎找不到我要找的东西。
我的用例如下:
总而言之:仅给定一个PdfDocument,如何从中获取/创建一个byte[]?
这是我的代码:
public async Task<BaseResponse> Handle(ReceiveEmailCommand command, CancellationToken cancellationToken) {
var ms = new MemoryStream(command.attachments.First().Content)
var extractedDocument = pdfService.PreparePdfDocument(ms);
var analyzedDocument = await formsRecognizerService.AnalyzeDocument(extractedDocument);
// Do stuff with the analyzed document...
var response = await FileWebService.AddAnalyzedDocumentToFileSystem(analyzedDocument);
}
函数AnalyzeDocument需要一个Stream参数。我想传递类似的东西
new Stream(extractedDocument.GetReader().Stream)
Helper函数实现如下:
public PdfDocument PreparePdfDocument(MemoryStream ms)
{
PdfDocument extractedDoc;
var pdfReader = new PdfReader(ms);
var pdf = new PdfDocument(pdfReader);
var doc = new Document(pdf);
var matches = GetNumberWithPages(pdf);
if (matches.Count > 0)
{
var pageRange = matches
.Where(x => x.Number == "125")
.Select(x => Convert.ToInt32(x.PageIndex))
.ToList();
extractedDoc = SplitPages(pdf, pageRange.First(), pageRange.Last());
}
else
{
// If we couldn't parse the PDF then just take first 4, 3 or 2 pages
try
{
extractedDoc = SplitPages(pdf, 1, 4);
}
catch (ITextException)
{
try
{
extractedDoc = SplitPages(pdf, 1, 3);
}
catch (ITextException)
{
try
{
extractedDoc = SplitPages(pdf, 1, 2);
}
catch (Exception)
{
throw;
}
}
}
}
return extractedDoc;
}
private static List<Match> GetNumberWithPages(PdfDocument doc)
{
var regex = new Regex(@"\s+([0-9]+)\s+(\([0-9]+\/[0-9]+\))\s+Page\s+([0-9])\s+of\s+([0-9]+)");
var matches = new List<Match>();
for (int i = 1; i <= doc.GetNumberOfPages(); i++)
{
var page = doc.GetPage(i);
var text = PdfTextExtractor.GetTextFromPage(page);
if (!string.IsNullOrEmpty(text))
{
var match = regex.Match(text);
if (match.Success)
{
var match = EvaluateMatch(match, i, doc.GetNumberOfPages());
if (match != null)
{
matches.Add(match);
}
}
}
}
return matches;
}
private static Match? EvaluateMatch(Match match, int pageIndex, int totalPages)
{
if (match.Captures.Count == 1 && match.Groups.Count == 5)
{
var match = new Match
{
Number = match.Groups[1].Value,
Version = match.Groups[2].Value,
PageIndex = pageIndex.ToString(),
TotalPages = totalPages.ToString()
};
return match;
}
else
{
return null;
}
}
public PdfDocument SplitPages(PdfDocument doc, int startIndex, int endIndex)
{
var outputDocument = CreatePdfDocument();
doc.CopyPagesTo(startIndex, endIndex, outputDocument);
return outputDocument;
}
public PdfDocument CreatePdfDocument()
{
var baos = new ByteArrayOutputStream();
var writer = new PdfWriter(baos);
var pdf = new PdfDocument(writer);
return pdf;
}
我很难理解如何从PdfDocument获取内容。
你不知道!
当您创建要写入的PdfDocument
时,您可以使用PdfWriter
对其进行初始化。该PdfWriter
已被初始化以写入某处。如果您想访问最终的PDF,您必须关闭PdfDocument
并在某处查看它。此外,从PdfWriter
中检索它也不容易,因为它被包裹在其中的许多层中。因此,您应该在附近的某个地方保留对它的引用。
因此,您的ByteArrayOutputStream
通常不会隐藏在某个方法CreatePdfDocument
中创建,而是在基本方法中创建并作为参数转发给其他方法。然后您最终可以检索其数据。如果您需要像这样隐藏创建您的ByteArrayOutputStream
,您可以返回PdfDocument
和ByteArrayOutputStream
的对
而不是<普通code>PdfDocument。
顺便说一下,这种架构背后的想法是iText试图尽早将尽可能多的PDF内容写入某个地方的输出并释放内存。这允许它创建大型文档,而不需要同样大的内存。
当我返回流时,我无法访问关闭的流
ByteArrayOutputStream
本质上是一个MemoryStream;因此您可以特别调用ToArray
来检索完成的PDF,即使它已关闭。
如果您需要将ByteArrayOutputStream
作为常规流,只需为您的编写器调用PdfWriter. SetCloseStream(false)
,以防止PdfDocument
的关闭
也关闭流。