How to display multiple pdfs in a FlexLayout row?

Hi,

Our Xamarin Forms app has a Gallery where we can display collections of images on a FlexLayout. For jpgs we use thumbnails. The user can click on a thumbnail to see the full image full screen.

We also have a collection of PDFs which we use the SF PDFViewer to fill in, draw on and other manipulations and finally to save.

I've been tasked with adding a representation of the PDFs to the Gallery on a row of their own. How can I get a thumbnail of a PDF using Syncfusion tools? Or do you have an alternative  suggestion for representing up to, say, 5 PDFs, on a row of a FlexLayout?  (the 5 representations of the PDFs can scroll off the device)

Thanks for your help.

Will


13 Replies 1 reply marked as answer

VD Vikram Devaraj Syncfusion Team August 17, 2021 05:39 PM UTC


Hi will,

 
We also have a collection of PDFs which we use the SF PDFViewer to fill in, draw on and other manipulations and finally to save.I've been tasked with adding a representation of the PDFs to the Gallery on a row of their own. How can I get a thumbnail of a PDF using Syncfusion tools? 
We assume that you want to show the first page of the PDF document as a thumbnail image in your gallery to represent each PDF files. The SfPdfViewer.ExportAsImage method can be used to convert the first page of the PDF to image and the image can be shown as thumbnail.

 
Please find the UG link for Export as image ,
https://help.syncfusion.com/xamarin/pdf-viewer/export-as-image

 
Please let us know whether this solution satisfies your requirement. If not, please let us know more details about your requirement and how you want to achieve it. 
Or do you have an alternative suggestion for representing up to, say, 5 PDFs, on a row of a FlexLayout? (the 5 representations of the PDFs can scroll off the device) 
We cannot think of any other way better than thumbnails to represent a PDF file in a gallery. Kindly let us know if converting the first page of each PDF to thumbnail using the ExportAsImage API as we mentioned above satisfies your requirement 

Regards,
Vikram D

 



WA Will Autio August 19, 2021 03:52 PM UTC

Hello Vikram D,

That looks like a great solution to my question. Unfortunately I need to deal with some obstinate bugs and have not been able to fully test your solution. I hope to get back to this soonest.

Regards,

Will



VD Vikram Devaraj Syncfusion Team August 20, 2021 10:32 AM UTC

Hi Will,   
  
Thank you for the update. We will wait to hear further updates from you.   
  
Regards,   
Vikram D




WA Will Autio August 23, 2021 08:07 PM UTC

Hi Vikram D,

What is the current method to read a file in the local file system and convert it to a stream?

I saw ways to read it from an embedded pdf.


Thanks!

Will



VD Vikram Devaraj Syncfusion Team August 24, 2021 01:39 PM UTC

Hi Will,

Please find the KB link below to read a file in the local file system and convert it to a stream.
 



WA Will Autio August 26, 2021 11:44 PM UTC

Hello Vikram D.

Thanks for your help. But I am not there quite yet.

1) Thanks to you , I can read a PDF from the system files. As proof that it worked, I have displayed a portion of it in a page.

2) Now I try to take the PDF that was just read in and create a jpg from the first page. That does not display.

3) In case I messed up the display portion, I wrote out the jpg and read it in again and tried to display it. That does not work.


Of the following two code snippets, one is the code-behind that manipulates the PDF to JPG (and the rest). Then there is the XAML.


        public async void TestForPDFs()

        {

            long PrjinforID = Util._selectedProjectAll.project.prjinfoID;

// the next line hits sqlite for the PDFs related to the project. There is only one PDF in this case.

            List<Docs> myDocs = Table_Docs.getDocsByProject(PrjinforID);

            string fileToGet = "";

            string imageName = "";


            if (myDocs.Count > 0)

            {

// The sqlite table has, among other things, the local path to the PDF. That gets stored in fileToGet.

                fileToGet = myDocs[0].DocsPath;


// The following is from some Syncfusion code. It works because I can display the PDF.

                if (Device.OS == TargetPlatform.Windows || Device.OS == TargetPlatform.WinPhone)

                    //Obtain the PDF stream from the UWP implementation of IFileHelperService. It is an asynchronous process

                    //Since constructor cannot be async, this process must be done in another method

                    SetFileStreamAsync(fileToGet);


                else

                    pdfStream = DependencyService.Get<IFileHelperService>().GetFileStream(fileToGet);

            }



            // now let's take the pdfStream and turn it into a jpg

            // https://help.syncfusion.com/xamarin/pdf-viewer/export-as-image


            //Initialize the SfPdfViewer

            SfPdfViewer pdfViewerControl = new SfPdfViewer();


            //Load the PDF document as stream

            pdfViewerControl.LoadDocument(PdfStream);


            //Export the page of PDF document to image stream with the given index;

            Stream ImageFromPDFstream = pdfViewerControl.ExportAsImage(0);


            GM.FileImgFromPDF = ImageSource.FromStream(() => ImageFromPDFstream); 

 // some of the original code=>  ImageSource.FromStream(Func < System.IO.Stream > stream);


            //===================================================


            // This part writes the captured image to the android disk

            // it also takes the name of the PDF and changes .pdf to .jpg

            imageName = fileToGet.Replace("pdf", "jpg");


            using (Stream fileHandler = File.OpenWrite(imageName))

            {

                byte[] imageBuffer = new byte[ImageFromPDFstream.Length];

                ImageFromPDFstream.Read(imageBuffer, 0, (int)ImageFromPDFstream.Length);

                await fileHandler.WriteAsync(imageBuffer, 0, imageBuffer.Length);

            }


            // so, that is supposed to write the image out.

            // now lets read it in and display it.

            GM.FileImg = ImageSource.FromFile(imageName);

        }


And here is the XAML:


            <Grid x:Name="pdfViewGrid">

                <syncfusion:SfPdfViewer x:Name="pdfViewerControl" InputFileStream="{Binding PdfStream }"

                                        WidthRequest="100" HeightRequest="200"/>   // this only shows the top bit of the PDF, but enough to show me that it got there.

            </Grid>


            <Label Text="FileImg"/>

            <Image Source="{Binding GM.FileImg}"

                            Aspect="AspectFit" HeightRequest="60"

                            WidthRequest="90"/>



            <Label Text="FileImgFromPDF"/>

            <Image Source="{Binding GM.FileImgFromPDF}"

                            Aspect="AspectFit" HeightRequest="60"

                            WidthRequest="90"/>


=================================


I got these two messages in the debug output:

[Drawable] Unable to decode stream: android.graphics.ImageDecoder$DecodeException: Failed to create image decoder with message 'unimplemented'Input contained an error.

[ImageView] resolveUri failed on bad bitmap uri: /data/user/0/com.itraxonline.itraxmobile/files/Pictures/2107K001_i-Trax_Work_Authorization_Form_Siging16050310351624310052_2021Aug26_092048.jpg


The part that says "Failed to create image decoder ..." causes me concern.

The uri, is where I saved the jpg to.


I have also included a copy of the PDF being tested with. Does it make a difference in this case if it is a form with filled in fields? This is the original form with no fields filled in.


Any further questions please  send them my way.


I sure appreciate your help!

Regards,

Will


Attachment: PDFIssue_663bd0b5.7z


VD Vikram Devaraj Syncfusion Team August 27, 2021 06:34 PM UTC

Hi Will,

 
We were unable to reproduce the issue based on provided details. While analysis your code snippet we suspect that instead of  using  pdfViewerControl.ExportAsImage(0), you can try to pass the page index parameter as 1 like pdfViewerControl.ExportAsImage(1) and check for the result. 
 
Kindly share the following details to analyze more on this issue and assist you with the better solution    
    1. simple sample which replicate the same issue.
    2. SfPdfViewer version.
    3. Device info.

Regards,
Vikram
 



WA Will Autio August 30, 2021 11:41 PM UTC

Hello Vikram,


Thanks again for your reply.

The attached 7z file is an app that is supposed to read an embedded PDF, write it out (to prove that it got read), then convert the first page of the PDF into an image and display it. (I really only need the image displayed, but for testing I also display a part of the PDF)


If you search for

pdfViewerControl.LoadDocument(PdfStream);


1) You will see the line where the app crashes. It is different than what I previously described because I was not able to replicate it on a smaller scale.


2) I used an embedded file because I was not able to store a pdf locally (in a timely manner). What I really need is to read a local PDF, convert the first page into an image and display it. (actually, I will be reading the Paths for several PDFs from SQLite, getting an image of page 1 of each and displaying them in a CollectionView. I trust that if I can do this for one file, the rest will follow. The general flow of our app is to download master copies of several PDF files, have them modified by the app (by our staff or clients - fill in form fields, draw diagrams,...), stored locally as well as uploaded to our server. The locally stored files may be used to create an image for each PDF and display - as I am working on here. I include this bit to give you more context.)


In my app I am using 19.2.0.56

In the sample app - 19.2.0.57

I am loading it onto a Samsung S10e using Android 11.


Best Regards,

Will


PS. I tried several times to upload my zipped project for the app but it repeatedly failed. I even changed the extension as sometimes that helps. So, I put the sample app on OneDrive. Please get the samples zip file from there.


Now I get "Forum submission was unsuccessful" .


What??

----------------

So, I removed the OneDrive link and will try again.

Now I can't even put a check in the "I am not a Robot" box.

The next step is to go to a different pc and try it all again. If you get this, you will know it worked.


This looks promising. I copied the zip to my office computer and was then able to upload it to this submission. Now I'll try to submit it.



Attachment: PDFToImage_459e725c.zip


VD Vikram Devaraj Syncfusion Team August 31, 2021 11:54 AM UTC

Hi Will,


I have made some changes in your provided sample. Please check the modified sample below and let us know that the provided sample will solve your issue. If the provided sample is not satisfied or resolve your problem please update us, what should we need to change in the sample to provide better solution for your requirement.


Sample: https://www.syncfusion.com/downloads/support/directtrac/general/ze/ModifedSample1487469054.zip


Regards,
Vikram
 


Marked as answer

WA Will Autio August 31, 2021 06:38 PM UTC

Hello Vikram,

Thanks for your thorough revision to my sample app. I appreciate the effort that you put in to it.


When I downloaded and unzipped it, I ran it immediately and got an error at this line:

Java.IO.FileOutputStream outs = new Java.IO.FileOutputStream(file);
When I searched for
Java.IO.FileOutputStream
the only exceptions that is says it throws are:
FileNotFoundException
SecurityException
The message that I am getting is:
**System.Reflection.TargetInvocationException:** 'Exception has been thrown by the target of an invocation.'

I googled the Exception and also the code but found nothing useful.

Here is the class involved. I did some slight reformatting. Otherwise it is as I received it. I also changed the min and max Android versions to 8 and 11. But that did not change the results.

I test on a Samsung Galaxy S10e real phone.

Regards,

Will


namespace PDFToImage.Droid
{
    public class SaveAndroid : ISave
    {
        public string Save(MemoryStream stream)
        {
            string root = null;
            string fileName = "SavedDocument.jpg";
            if (Android.OS.Environment.IsExternalStorageEmulated)
            {
                root = Android.OS.Environment.ExternalStorageDirectory.ToString();
            }
            string newpath = root + "/Syncfusion";


            Java.IO.File myDir = new Java.IO.File(root + "/Syncfusion");
            if (myDir.Exists() == false)
            {
                myDir.Mkdir();
            }
            Java.IO.File file = new Java.IO.File(myDir, fileName);
            string filePath = file.Path;
            if (file.Exists())
            {
                file.Delete();
            }


            // Following gives: **System.Reflection.TargetInvocationException:** 'Exception has been thrown by the target of an invocation.'
            Java.IO.FileOutputStream outs = new Java.IO.FileOutputStream(file);
            outs.Write(stream.ToArray());
            var ab = file.Path;
            outs.Flush();
            outs.Close();
            return filePath;
        }
    }
}

Thanks for looking at this again.


Attachment: PDFToImage_7a64ac06.zip


VD Vikram Devaraj Syncfusion Team September 1, 2021 10:52 AM UTC

Hi Will,

This issue is due to disabled storage permission. Please enable or allow this application storage permission using your mobile settings and then run this application will not throw this exception.
 

Steps to turn permissions on or off
 
  1. On your Android device, open the Settings app .
  2. Tap Apps & notifications.
  3. Tap the app you want to update.
  4. Tap Permissions.
  5. Choose storage permissions and enable
 
 
Regards,
Vikram
 



WA Will Autio September 1, 2021 05:00 PM UTC

Hello Vikram,

Congratulations! You managed to guide me thru that process.

In Settings I had to enable "Allow management of all files." Before that I had only enabled "Allow access to media only."

Now, as long as I can transform what you did in the sample app into our main app, we'll be golden.

Thanks so much for your help. This last one had such a seemingly unrelated error message, that I may have never solved it.

Regards,

Will



VD Vikram Devaraj Syncfusion Team September 2, 2021 12:47 PM UTC

Hi Will,

You are most welcome. For any further information or query feel free to contact syncfusion support.
 

Regards,
Vikram

 


Loader.
Up arrow icon