Reputation: 122
I am creating a mobile application with Xamarin Forms where the user can view the result of exams done. The result of the exams comes from a database in a byte array format and I need to somehow convert the byte array into a PDF and display it to the user. I saw that I can use a WebView to display a PDF, but would need to save it to the device and then display it. Would anyone know how I can convert the byte array to PDF and display it in a WebView without having to save it or do it otherwise?
Thanks in advance.
Upvotes: 1
Views: 4354
Reputation: 74094
Using pdf.js
makes it really easy: https://mozilla.github.io/pdf.js/
Add a WebView
to your Forms' Page and setup the dependency code to obtain the baseurl path per platform
Add the pdf.js
and pdf.worker.js
to your application projects (BundleResource
for iOS and AndroidAsset
for Android)
Convert your PDF stream to a Base64-string (via a MemoryStream
if needed) and embed that string into a HTML-based string.
Use JavaScript (atob
) to decode that base64 string and setup pdf.js /
pdf.worker.jsto render to a
canvas` defined in your html.
<StackLayout x:Name="webViewContainer" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<WebView x:Name="webView" BindingContext="{x:Reference webViewContainer}" WidthRequest="{Binding Width}" HeightRequest="{Binding Height}"/>
</StackLayout>
Note: Using a PDF via bundled resource, substitute your stream there....
var baseUrl = DependencyService.Get<IBaseUrl>().Get();
string base64Pdf;
using (var stream = await FileSystem.OpenAppPackageFileAsync("Dank Learning 1806.04510.pdf"))
using (var memoryStream = new MemoryStream())
{
await stream.CopyToAsync(memoryStream);
base64Pdf = Convert.ToBase64String(memoryStream.ToArray());
}
var html = @"
<html>
<head>
<script type=""text/javascript"" src=""pdf.js""></script>
<script type=""text/javascript"">
window.onload=function(){
var pdfData = atob('SUSHIHANGOVER');
var pdfjsLib = window['pdfjs-dist/build/pdf'];
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdf.worker.js';
var loadingTask = pdfjsLib.getDocument({data: pdfData});
loadingTask.promise.then(function(pdf) {
console.log('PDF loaded');
var pageNumber = 1;
pdf.getPage(pageNumber).then(function(page) {
console.log('Page loaded');
var scale = 1.5;
var viewport = page.getViewport(scale);
var canvas = document.getElementById('the-canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: context,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.then(function () {
console.log('Page rendered');
});
});
}, function (reason) {
console.error(reason);
});
}
</script>
</head>
<body>
<h1>StackOverflow / Base64 PDF</h1>
<canvas id=""the-canvas"" style=""border: 1px solid""></canvas>
<h2>by SushiHangover</h2>
</body>
</html>
";
html = html.Replace("SUSHIHANGOVER", base64Pdf);
webView.Source = new HtmlWebViewSource
{
BaseUrl = baseUrl,
Html = html
};
Upvotes: 2