Perspective PDF Viewer without WebDev

So I know how to load PDFs from a database using the WebDev module. However I need to try and see if there is a way to load a PDF from a database without the WebDev module. Any ideas how to get it done? The PDFs are sitting in a database as a blob format.

3 Likes

Using Perspective is there any way to view a PDF without the Web Dev module?
Iā€™ve seen a script here that uses system.file.openFile to open specific files.

# This code would prompt the user to open a file of type 'pdf' from their stored documents folder. If None is returned, it means the user canceled the open dialog box.
# Note: the computer running this code needs to have network access to the "fileserver" computer.
path = system.file.openFile('pdf', '\\fileserver\PDF_Storage')
if path != None:
   # do something with the file

I donā€™t think so. Data URLs might workā€¦but probably only for very small PDFs, if at all (and have some serious performance implications anyways).

1 Like

Ugh. OK not what I was hoping. Itā€™s already tough enough for the Perspective license, then to try and get the customer to go for another module just to support this feature is almost an impossible sell.

We have an entire manual system built around PDFs in the database connected to our popups as well as a system library for the end user to put whatever they want into it. It all works awesome in Vision and was hoping that we could replicate that just with the Perspective license straight up. Itā€™s unfortunate that this specific component relies heavily on another module.

Has there been any discussion of throwing in the WebDev as part of the perspective license?

2 Likes

Put your files in webserver/main/ā€¦ and it publishes them like an IIS server would, you can then access them

Currently they are all in a database that we use across both Vision and eventually Perspective. If we can keep them in the database that would be ideal. that way there isnā€™t multiple copies running around. Plus we have a self service feature where the plant can upload what they want into the database so itā€™s available everywhere.

Can you use webdav/IIS to publish those files to the network?

Iā€™d like to be able to use Ignition to serve up files to the PDF Viewer in a Perspective environment similar to how it is being done in Vision. If there is an inherit limitation in the PDF Viewer Component, and it seems that there is, that in order to send it files you need to purchase another module, then we will probably just do a system.perspective.download for the file after it gets put together from the database. Iā€™d rather have an all in one solution, but that is the second choice.

Most of our customers are of the lower budget variety with a couple of workstations running Ignition. So the addition of IIS or other servers in order to support sending a file from the database to the front end is a non starter in these environments.

I think our backend could theoretically support this in a way that would be reasonable - I made a ticket to investigate.

Thanks I appreciate it. If you could just ping this thread with what you find out that would be awesome.

@PGriffith Do you know if anything came of this investigation?

@bschroeder
What you can do is have a gateway function that saves the file to the Ignition\webserver\webapps\main folder on the client. Ignition then will automagically render the image as a web path then {ip}/filename. I normally make a documents folder and save everything in there (so it is {ip}/documents/filename).

1 Like

Does this data get syncā€™d up between gateways in redundancy?

The ticket got changed around a bit, but ultimately ended up as a feature request on the Perspective teamā€™s backlog. Itā€™s at a medium priority, so all other things being equal itā€™ll get picked up ~soon, but bugs generally take priority over features, so itā€™s hard to give any kind of timeline.

The theoretical implementation would be a getPdfBytes() extension function, so that you can do whatever you need to on the backend to get your PDF content loaded, and the component will automatically handle ā€˜fetchingā€™ it to the frontend.

1 Like

Awesome. I completely understand prioritizing bugs before this. Iā€™m just glad that this is in progress. I appreciate your response.

Any updates on this feature? We need to be able to display PDF files by providing the bytes stored in a database. We are opting for this approach instead of the Report Viewer component because our reports take longer than the fixed timeout period of the component. So, weā€™ll run the reports on a schedule in the morning, then just provide links for users to see the finished PDF. Also, the Report Viewer component canā€™t seem to handle downloading large report PDFs or opening them in a new windowā€¦we always get the dreaded ā€œFailed to Fetchā€ error.

1 Like

This does PDF files as easily as images....

{ /shameless plug }

Thanks Phil. Iā€™ll do some testing with this and let you know if I find anything. If you would have finished this a day sooner I would have thought it to be a cruel April Fools joke. :slight_smile:

One nice feature that cloud-based systems offer are expiring urls (and super long obfuscated GUID parameters). From what I understand on this module, if someone is crafty enough to enter in a different id parameter, they would access Blob data from a DB entry that they should have access to. Perhaps you are leaving the obfuscating part as an exercise for the student?

Correct. The security model for Named Queries is go/no-go just on user/roles/zones. No inspection of parameter values nor return values is done to qualify access. If you need that, stick with the WebDev module.

This module is for simple applications.

Let me qualify this.

The module doesn't care how complicated the Named Query is. If you provide a table with guid, id, expires triplets, you could change my sample query to something like this:

Select blob as "Content", 'image/png' as "ContentType"
From images Inner Join transientImages On images.id = transientImages.id
Where transientImages.guid = :guid And current_timestamp < transientImages.expires

When you construct an image URL, generate a guid for it on the fly and insert it into transientImages with a suitable expires value.

1 Like