Adding the initialDoc path in Java JSP Struts project

Which product are you using?

PDF.js Express Version

Detailed description of issue
{ I’m working on a Java JSP Struts project which has previously implemented PDF.js for previewing documents. Because of the the PDF.js library didn’t support watermarks option I decided to move to PDF.js Express.

The getImage.do will go to the GetImageAction.java page and generate and get the PDF file,
I have added the previous implementation code below.

I have tried to add the previous location URL path like this

encodeURIComponent('${pageContext.request.contextPath}/getImage.do?imageDocID='+document.getElementById('imageDocID').value);

but this is not a file path, so the webViewer shows this error by identifying .do as the file extension.

File extension do%3fimagedocid%3dww222244 is not supported. Please see http://r.pdftron.com/fileformats for a full list of file formats supported by WebViewer. If this file is actually valid then you can pass the 'extension' option with the intended file extension e.g. const doc = await Core.createDocument("http://domain/file11243. php", [extension: "pdf"}) the initialDoc value is %2FWEB_SSD%2FgetImage.do%3FimageDocID%3DWW222244
}

So do you any other method to add the initialDoc value as my previously implemented method?

Expected behaviour
{ I want to view the generating PDF via the pdf.js express viewer.}

Does your issue happen with every document, or just one?
{Every Document}

Link to document
{The document is created as a byte stream, So I don’t have any document location to add it the initialDoc property.}

Code snippet

The below code snippet is the previous implementation
{
html body

<iframe id="content" style='height: 600px; width: 98%; min-width: 900px;' scrolling="no" src=""></iframe>

script

<script type="text/javascript">
    $(document).ready(function() {
        var base='web/viewer.html?file=';
        var subUrl=encodeURIComponent('${pageContext.request.contextPath}/getImage.do?imageDocID='+document.getElementById('imageDocID').value);
        var url=base+subUrl+'#page=1';
        $('#content').attr('src',url);
    });
</script>

struts-config

<action  
    path="/getImage"
    type="web.ead.webapp.ssd.common.action.GetImageAction"
    scope="request">
</action>

GetImageAction.java

public class GetImageAction extends GenericAction {
    
    static Object imageServerLock = new Object();
    
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException, Exception {

        UserProfile userProfile = (UserProfile) request.getSession().getAttribute("UserProfile");
        
        ActionForward actionForward = null;
        String imageDocID = request.getParameter("imageDocID");
        if (actionForward == null)
        {
            byte[] appletData = ImageManager.getMod2TifImage(imageDocID);
            ObjectOutputStream outputToApplet = new ObjectOutputStream(response.getOutputStream());
            outputToApplet.writeObject(appletData);
            outputToApplet.flush();
            outputToApplet.close();

            actionForward = null;
        }
        
        

        return actionForward;

        ActionForward actionForward = null;
        try{

            actionForward = super.execute(mapping, form, request, response);
            
            String imageDocID = request.getParameter("imageDocID");

            System.out.println(new Timestamp(System.currentTimeMillis()).toString() + "\trequest.getRemoteAddr() "
                    + request.getRemoteAddr() 
                    + " Utility.getClientIp(request) : "
                    + Utility.getClientIp(request) + " - " + imageDocID
                    + " UserProfileID: " + userProfile.getUserProfileID());
            byte[] image = null;
            synchronized (imageServerLock) {
                
                if(request.getSession().getAttribute("IMAGE-"+imageDocID) != null)
                    image = (byte[]) request.getSession().getAttribute("IMAGE-"+imageDocID);
                
                if (actionForward == null) {
                    byte[] dest = addWatemark(image);
                    
                    try{
                        PdfReader reader = new PdfReader(dest);
                        int pages = reader.getNumberOfPages();
                    }catch(Exception ex){
                        ex.printStackTrace();
                        image = ImageManager.optimizePDF(image);
                        dest = addWatemark(image);
                    }
                    
                    response.setContentType("application/pdf");
                    OutputStream outs = response.getOutputStream();
                    outs.write(dest);
                    outs.close();
                    actionForward = null;
                    if(request.getSession().getAttribute("IMAGE-"+imageDocID) != null)
                        request.getSession().removeAttribute("IMAGE-"+imageDocID);
                    
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }

        LoggerUtils.info(this.getClass().getName() + " - execute method --> Exit");
        return actionForward;
    }

}

Hello ravinduyasithgtx,

Can you provide a minimal runnable sample to reproduce the issue, since this integration is complex.

Best regards,
Tyler

Hello tgordon,

Simply, is there any way to load the pdf file if I have the byte stream?
In my project the PDF file generated as an byte stream, because of that in the WebViewer initialDoc property I cannot set a byte stream.

I just need to know that how to input a byte stream to the PDF.js Express.

Thank you

Hello ravinduyasithgtx,

If you convert the bytestream into a usable state like a ArrayBuffer or Blob, you can then call loadDocument or the initalDoc parameter.

Best regards,
Tyler

1 Like

Hello tgordon,

<script type="text/javascript">
$(document).ready(function() {
	
	function getPDFData(imageDocID) {
        // Get the PDF data from the `getImage.do` action
        var xhr = new XMLHttpRequest();
        xhr.open('GET', '${pageContext.request.contextPath}/getImage.do?imageDocID=' + imageDocID);
        xhr.responseType = 'arraybuffer';
        xhr.onload = function() {
        	console.log(xhr.status);
            if (xhr.status === 200) {
            	console.log('document loaded');
            	console.log(xhr.response);
                // Return the PDF data
                return xhr.response;
            } else {
                // Handle error
                console.log('Error getting PDF data: ' + xhr.statusText);
            }
        };
        xhr.send();
    }
    
WebViewer({
  path: './pdfJSExpress/lib', // path to the PDF.js Express'lib' folder on your server
  licenseKey: 'xxxxxxxxxxxxxxxxxxxxxx',
  loadDocument: getPDFData(document.getElementById('imageDocID').value),
}, document.getElementById('content'))
.then(instance => {
  // now you can access APIs through the WebViewer instance
  const { Core, UI } = instance;

  // adding an event listener for when a document is loaded
  Core.documentViewer.addEventListener('documentLoaded', () => {
    console.log('document loaded');
  });

  // adding an event listener for when the page number has changed
  Core.documentViewer.addEventListener('pageNumberUpdated', (pageNumber) => {
    console.log(`Page number is: ${pageNumber}`);
  });
});
});
</script>

The getPDFData method returns an ArrayBuffer. But I couldn’t view the pdf file.

Thank you.

Hello ravinduyasithgtx,

I’m not exactly sure how this would work because I do not have a runnable sample, however, I suggest calling your XHR request after the documentLoaded event is fired by WebViewer. This ensures the PDF data is ready to be fetched.

Best regards,
Tyler