vaadin-component-factory / vcf-pdf-viewer-flow

Vaadin Addon for providing pdf viewing functionality
Apache License 2.0
9 stars 6 forks source link

Print buton does not work (print.js error) #24

Open scrmtrey91 opened 2 years ago

scrmtrey91 commented 2 years ago

Print button is displayed correctly but it does not work, it does not print the PDF.

image

Error is in javascript of print.js:

Uncaught (webpack-internal:///../target/flow-frontend/print-js/dist/print.js:468:9)

image

I need this feature to work for clients. Now they download the PDF first then print it with windows or browser native viewer.

But i really want to use your addon because it is great and clean with only the necessary functions.

paodb commented 2 years ago

Can you share a reproducible example or more information about your scenario (vaadin version, component version, if this is browser specific, etc)? I did a quick test in the latest Vaadin version and latest component version and printing works okay. See pdf-viewer-test.zip.

scrmtrey91 commented 2 years ago

Your example works (printing). Hmm interesing, maybe it works because of springboot. I am not using springboot.

I am using java 17, pnpm, vaadin-cdi, some other addons, webpack latest vaadin and latest addon version. The app is deployed on Payara 5.2022.3, the application is war not jar.

Sorry i can not share the real app with you.

I tried different browser (safari lates osx) and throws the same error.

scrmtrey91 commented 2 years ago

New error:

Uncaught Not Found (webpack-internal:///../target/flow-frontend/print-js/dist/print.js:468:9)
scrmtrey91 commented 2 years ago

I looked into developer tools , console in chrome...and it looks like the PDF cannot be fetch when the print button is clicked.

The reason why print.js does not work (no data pdf to print).

image

scrmtrey91 commented 2 years ago

It seems vaadin build wrong path to dynamic content. It is missing the app context root before /VAADIN/...

scrmtrey91 commented 2 years ago

Download button is using correct URL path to dynamic content :

image

It is using context root path befoe /VAADIN/ , thats why resource is resolved and download works.

scrmtrey91 commented 2 years ago

Steps to reproduce error:

1) Go to : https://vaadin.com/hello-world-starters

2) Choose started : VAADIN 23 - CDI

3) add pdf addon + pdf files in resources + web pack flag

4) Run payara , deploy war

5) Print PDF NOT working, download working OK

Zip project sample not working properly: skeleton-starter-flow-cdi-23.zip

ARCHERS commented 2 years ago

I have a similar issue with both the download and print function. I'm using Spring boot, Vaadin 23 and java 17. Rather than reading a pdf file from disc as in the pdf-viewer-test sample provided above (which works fine with my setup), I'm using JasperExportManager to export to a temporary pdf file as follows:

jasperPrint = JasperFillManager.fillReport(filePath, param, conUser); File reportFile = File.createTempFile("output", ".pdf"); JasperExportManager.exportReportToPdfFile(jasperPrint, reportFile.getAbsolutePath()); FileInputStream fs = getInputStream(reportFile); StreamResource resource = new StreamResource(displayName, () -> fs); pdfViewer = new PdfViewer(); pdfViewer.setSrc(resource);

The pdf displays OK in the viewer, but both print and download fail with "java.io.IOException: Stream Closed" error (even though I have not programmatically closed the stream). I think this means the stream has already been consumed in setting the Viewer and unavailable to print/download. Any help appreciated.

scrmtrey91 commented 1 year ago

any news about that ?

scrmtrey91 commented 1 year ago

Any fixes for print button not working ?

It takes wrong URL for file (without context root of app) thus file not found 404 and print button not working.

scrmtrey91 commented 1 year ago

The problem is in file "print.js" in line 811:

params.printable = /^(blob|http|\/\/)/i.test(params.printable) ? params.printable : window.location.origin + (params.printable.charAt(0) !== '/' ? '/' + params.printable : params.printable); // Get the file through a http request (Preload)

It only gets origin of window which does not include app context root.

If the app is deployed on server behind reverse-proxy (the url of app is mapped by external domain, context path is hidden), then the print works.

Example: 1) https://localhost:8181/AppRoot -> print not working (it only gets https://localhost:8181/) 2) https://app-root-proxy/ -> print works (correct origin because of no port and context root: https://app-root-proxy/)

ARCHERS commented 1 year ago

I now have the download and print buttons working with an inputstream source on the fly using the following code:

            jasperPrint = JasperFillManager.fillReport(filePath, param, conUser);
            byte[] byteArray = JasperExportManager.exportReportToPdf(jasperPrint);
            resource = new StreamResource(displayName, () -> new ByteArrayInputStream(byteArray));
            resource.setContentType("application/pdf");
            pdfViewer.setSrc(resource);

I had originally created a temp file from JasperPrint, but here the StreamResource is derived from a PDF byte array by way of ByteArrayInputStream. I'm using pdfviewer version 2.7.2 in Vaadin 23.3.5.

scrmtrey91 commented 1 year ago

I have exact same code as you (from 1 year ago), always from byte array input stream (it is also jasper report byte pdf data).

BUT still does not work. Download working, print not working (because print.js build wrong URL path to get the PDF source, see the comments above).

pdfviewer version 2.7.2 in Vaadin 24.0.4 (but even with vaadin 23 does not work).

ARCHERS commented 1 year ago

So I'm running my code in development with no reverse proxy at http://localhost:8080/ - not tried it in production server yet. My issue (see previous post) was that when the InputStream is assigned to a variable before instantiating StreamResource, the PDF is displayed correctly in the viewer, but the download creates an empty PDF and the print does nothing because the stream is empty (had been consumed, but I don't get the print.js javascript error you described above). If the StreamResource is instantiated directly with "new ByteArrayInputStream(byteArray"), the PDF is populated correctly.

So this produces an empty (corrupt) PDF:

private InputStream is; //

is = new ByteArrayInputStream(byteArray);
resource = new StreamResource(displayName, () -> is);

But this works:

resource = new StreamResource(displayName, () -> new ByteArrayInputStream(byteArray));

However I think that may be different to your problem.

scrmtrey91 commented 1 year ago

Try running the app with context root instead.

Example: /AppName

https/localhost:8181/AppName

Without context root (empty) it is working.

But we have multiple war deployed , so we cannot have empty context root of app.

ARCHERS commented 1 year ago

You're right, I can reproduce the error by configuring the root context path. As you said above, it seems to be a problem with "window.location origin" in print,js which only gets the base URL. I think it should be window.location origin + window.location.pathname as per this:

https://www.samanthaming.com/tidbits/86-window-location-cheatsheet/

scrmtrey91 commented 1 year ago

Yp. Probably fix. I guess it will never be fixed.

TatuLund commented 1 year ago

@scrmtrey91 Are you customer of ours with some subscription tier? If yes, which one?

scrmtrey91 commented 1 year ago

We have Vaadin Pro Subscription.

gaugat commented 1 year ago

I think it should be window.location origin + window.location.pathname

Probably don't want the entire pathname. It will include the route path, which you don't want. You will want only context path and servlet mapping (vaadin.urlMapping) if configured.

jm2rodriguez commented 1 year ago

Hi, I'm facing the same problem. Finally I solve it by calling PdfViewer.setSrc() with a full url instead of the relative url generated by StreamResource. It works fine for me.

// Create your StreamResource StreamResource streamResource = new StreamResource(...);

StreamRegistration streamRegistration = VaadinSession.getCurrent().getResourceRegistry().registerResource(streamResource);

// Create a full string URI ... String uri = scheme + "://" + serverName + ":" + serverPort + contextPath + "/" + streamRegistration.getResourceUri();

// Create a PdfViewer instance and set the source with the full URI PdfViewer pdfViewer = new PdfViewer(); pdfViewer.setSrc(uri); ...

robinovsky commented 6 months ago

I solved it using same approach from @jm2rodriguez, but keeping it relative

        String contextPath = VaadinRequest.getCurrent().getContextPath();
        StreamRegistration streamRegistration = VaadinSession.getCurrent().getResourceRegistry().registerResource(streamResource));       
        String uri = contextPath + "/" + streamRegistration.getResourceUri();
        viewer.setSrc(uri);