簡體   English   中英

Blazor WASM 通過將大型 pdf 拆分為流來加載和顯示它們

[英]Blazor WASM Load and display large pdfs by splitting them as streams

我正在開發 Blazor WASM 應用程序,我希望我的用戶能夠輕松地在包含附加信息的特定頁面上打開 pdf 文件。 我不能自己分發這些文件或將它們上傳到任何類型的服務器。 每個用戶都必須自己提供。

因為文件最大為 60MB,所以我無法將上傳的文件轉換為 base64 並按照此處所述顯示它們。

但是,我不必顯示整個文件,只需加載所需的頁面 +- 它們周圍的一些頁面。

為此,我嘗試使用 iText7 ExtractPageRange() 這個答案表明,我必須重寫GetNextPdfWriter()方法並將所有流存儲在一個集合中。

class ByteArrayPdfSplitter : PdfSplitter {
public ByteArrayPdfSplitter(PdfDocument pdfDocument) : base(pdfDocument) {
}

protected override PdfWriter GetNextPdfWriter(PageRange documentPageRange) {
    CurrentMemoryStream = new MemoryStream();
    UsedStreams.Add(CurrentMemoryStream);
    return new PdfWriter(CurrentMemoryStream);
}

public MemoryStream CurrentMemoryStream { get; private set; }

public List<MemoryStream> UsedStreams { get; set; } = new List<MemoryStream>();

然后我想我可以合並這些流並將它們轉換為base64

var file = loadedFiles.First();

    using (MemoryStream ms = new MemoryStream())
    {
        var rs = file.OpenReadStream(maxFileSize);
        

        await rs.CopyToAsync(ms);

        ms.Position = 0;

        //rs needed to be converted to ms, because the PdfReader constructer uses a 
        //synchronious read that isn't supported by rs and throws an exception.
        PdfReader pdfReader = new PdfReader(ms);
        
        var document = new PdfDocument(pdfReader);
        var splitter = new ByteArrayPdfSplitter(document);
        
        var range = new PageRange();
        range.AddPageSequence(1, 10);
        
        var splitDoc = splitter.ExtractPageRange(range);

        //Edit commented this out, shouldn't have been here at all leads to an exception
        //splitDoc.Close();

        var outputMs = new MemoryStream();

        foreach (var usedMs in splitter.UsedStreams)
        {
            usedMs.Position = 0;
            outputMs.Position = outputMs.Length;
            await usedMs.CopyToAsync(outputMs);
        }
        
        var data = outputMs.ToArray();
        
        currentPdfContent = "data:application/pdf;base64,";
        currentPdfContent += Convert.ToBase64String(data);
        pdfLoaded = true;
    }

然而這不起作用。 有沒有人建議如何讓它工作? 或者也許我可以嘗試一個更簡單的解決方案。


編輯:

我仔細查看了調試,似乎生成的流outputMs始終為空。 所以這可能是我如何拆分pdf的問題。

在至少部分消除了我對無法從 blazor WASM 訪問文件系統意味着什么的誤解之后,我設法找到了一個可行的解決方案。

        await using MemoryStream ms = new MemoryStream();
        var rs = file.OpenReadStream(maxFileSize);

        await using var fs = new FileStream("test.pdf", FileMode.Create)
                
        fs.Position = 0;

        await rs.CopyToAsync(fs);
        fs.Close();
            
        string path = "test.pdf";
        string range = "10 - 15";
        var pdfDocument = new PdfDocument(new PdfReader("test.pdf"));
        var split = new MySplitter(pdfDocument);
        var result = split.ExtractPageRange(new PageRange(range));
        result.Close();


        await using var splitFs = new FileStream("split.pdf", FileMode.Open))
        await splitFs.CopyToAsync(ms);

        var data = ms.ToArray();
            
        var pdfContent = "data:application/pdf;base64,";
        pdfContent += System.Convert.ToBase64String(data);
        Console.WriteLine(pdfContent);

        currentPdfContent = pdfContent;

使用答案中的 MySplitter 類。

    class MySplitter : PdfSplitter
    {
        public MySplitter(PdfDocument pdfDocument) : base(pdfDocument)
        {
        }

        protected override PdfWriter GetNextPdfWriter(PageRange documentPageRange)
        {
            String toFile = "split.pdf";
            return new PdfWriter(toFile);
        }
    }

暫無
暫無

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

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