簡體   English   中英

如何使用 itext7 從 PdfDocument 中獲取 pdf byte[]?

[英]How to obtain pdf byte[] from PdfDocument using itext7?

我很難理解如何從 PdfDocument 獲取內容。 我從以前的問題中了解到,PdfDocument 會刷新內容以優化處理大型文檔。 如果我的 function 返回一個新的 PdfDocument,我如何讓 byte[] 傳遞給我的其他函數?

即使使用 PdfDocument.GetReader() - 我似乎也找不到我要找的東西。

我的用例如下:

  1. 從 email 附件中獲取 pdf 內容
  2. 將 pdf 傳遞給幫助器 function,后者從初始附件中提取特定頁面
  3. 將新的 PdfDocument 傳遞到 function 中,它調用 Azure 的 Forms 識別器 API 以將字段讀取到 Z45B668CFFDE693311

總結一下:僅給定一個 PdfDocument,我如何從中獲取/創建一個字節 []?

這是我的代碼:

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);
}

function AnalyzeDocument 需要一個 Stream 參數。 我想通過類似的東西

new Stream(extractedDocument.GetReader().Stream)

助手 function 實現如下:

        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 ,您可以返回一Pair PdfDocumentByteArrayOutputStream而不是普通的PdfDocument

By the way, the idea behind this architecture is that iText tries to write as much PDF content as possible to that somewhere output as early as possible and free the memory. 這允許它創建大型文檔,而無需類似大量的 memory。

當我返回 stream 時,我無法訪問已關閉的 stream

ByteArrayOutputStream本質上是一個MemoryStream 所以你可以特別調用ToArray來檢索完成的 PDF 即使它已經關閉。

如果您需要ByteArrayOutputStream作為常規 stream,只需為您的編寫器調用PdfWriter.SetCloseStream(false)以防止close PdfDocument也關閉 stream。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM