[英]Blazor WASM Load and display large pdfs by splitting them as streams
I'm working on a Blazor WASM App and I want my users to easily open pdf files on specific pages that contain additional information.我正在开发 Blazor WASM 应用程序,我希望我的用户能够轻松地在包含附加信息的特定页面上打开 pdf 文件。 I cannot distribute those files myself or upload them to any kind of server.
我不能自己分发这些文件或将它们上传到任何类型的服务器。 Each user has to provide them themselves.
每个用户都必须自己提供。
Because the files are up to 60MB big I cannot convert the uploaded file to base64 and display them as described here .因为文件最大为 60MB,所以我无法将上传的文件转换为 base64 并按照此处所述显示它们。
However I don't have to display the whole file and could just load the needed page +- some pages around them.但是,我不必显示整个文件,只需加载所需的页面 +- 它们周围的一些页面。
For that I tried using iText7 ExtractPageRange()
.为此,我尝试使用 iText7
ExtractPageRange()
。 This answer indicates, that I have to override the GetNextPdfWriter()
Method and to store all streams in an collection.这个答案表明,我必须重写
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>();
Then I thought I could merge those streams and convert them to base64然后我想我可以合并这些流并将它们转换为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;
}
This however doesn't work.然而这不起作用。 Has anyone a suggestion how to get this working?
有没有人建议如何让它工作? Or maybe a simpler solution I could try.
或者也许我可以尝试一个更简单的解决方案。
Edit:编辑:
I took a closer look in debug and it seems like, the resulting stream outputMs
is always empty.我仔细查看了调试,似乎生成的流
outputMs
始终为空。 So it is probably a problem in how I split the pdf.所以这可能是我如何拆分pdf的问题。
After at least partially clearing up my misconception of what it means to not being able to access the file system from blazor WASM I managed to find a working solution.在至少部分消除了我对无法从 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;
With the MySplitter Class from this answer.使用此答案中的 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.