Open PDF from Webclient

Please help me out here :?
I’m trying to use application.showURL(path); to open a PDF document and passing it the path to a valid document in the filesystem but it does not open.
No error messages, nothing at all.
The path is “file:///C:/server/temp/WebReports/ZZ0WDNM7.PDF” or similar a local path for the client.
If I paste the same path in the browser it opens just fine (if the document is saved locally on client).
I understand that the document needs to be on the server though? Anyway, I tried opening it on both server and client and neither worked.
In smart client the code works just fine.
Please help.

Cheers,
Maria

Hi Maria,

did you see this thread?
http://forum.servoy.com/viewtopic.php?f=9&t=12716&p=80499&hilit=open+pdf#p80499

mboegem:
Hi Maria,

did you see this thread?
http://forum.servoy.com/viewtopic.php?f=9&t=12716&p=80499&hilit=open+pdf#p80499

Thanks Marc.Thanks for the link, very helpful.
However I’m doing something wrong as my code is not working.
Here’s what I do:

	var path = getPath(); //the absolute path to the PDF, document physically exists on disk at that stage and can be opened in the file system
	
	var success = plugins.file.copyFile(path, fileName); //copy to server directory
	
	if(success) {
		
		var serverURL = application.getServerURL() 
		application.showURL(serverURL + "/" + fileName);
	}

The file is generated in another directory on server machine and I try to copy it to the server directory to enable openning it in the browser.
At the point where it should place a copy of the file in the server directory ‘success’ returns ‘true’ but the file is not there, therefore Apache complains “The requested resource (/ZZ0ZUVCP.PDF) is not available.”

What’s wrong with copying the file?

Cheers,
Maria

Maria,

in webclient you can just do: plugins.file.writefile(‘myfile.pdf’, vBinaryData)

than the webclient does the rest for you, popup that file for you.

vBinaryData, can be data from a database blob or just data that you read from a file: vBinaryData = plugins.file.readFile…

Hope this helps

Harjo:
in webclient you can just do: plugins.file.writefile(‘myfile.pdf’, vBinaryData)

than the webclient does the rest for you, popup that file for you.

Harjo,

I’m afraid that is not working.
When I do what you wrote, the file is written to the User/Downloads directory.
But that popup is not appearing.

But I must say also that the Jasper Viewer when using a Jasper report, is not doing a popup as well. Also in this case the pdf is written into the User/Downloads directory.
See this issue: Defect #177: Jasper viewer fails in webclient - Servoy JasperReports Plugin - ServoyForge

Could there be a relation between those 2 cases?

Because whatever I try, I’m not getting my pdf file shown in a webclient (5.1.4)

Martin

Than you have accepted (once) in your browser, to always download that file immediatly.
look into your browser settings under download settings… (always ask for me…)

or try different browsers, (IE, firefox, etc…)

directly show the pdf, you can try this:

viewtopic.php?f=9&t=12716&start=0&st=0&sk=t&sd=a&hilit=show+pdf+webclient

Harjo,

That is correct.

I tried it with the Jasper Report output and now it asks if I want to save the file.
But, I dont want to save the file, I want this file automatically opened, and that is not an option (in FF)
In IE8 I see quickly a browser window opened and disappearing immediately.

But opening a file from the server (somewhere on the server, not under servoy server directory like application_server\server\webapps\ROOT) and showing the file as pdf on the webclient, is still not working.

I have the following coding:

	var _server = plugins.it2be_tools.server()
	var _ext = 'pdf'		
	var _server_path
	var _slash = '\\'
	var _server_file_name = '\\somedir\\somesubdir\\myFile.pdf'
	
	_server_path = _server.getApplicationServerDir() + _slash + 'attachments' + _slash + _server_file_name;

	var _binary = _server.readFile(_server_path)
	if (! _binary)
		return;
	
	var _tmp_file = plugins.file.createTempFile('', '.' + _ext)
	if (! _tmp_file)
		return;
	
	plugins.file.writeFile(_tmp_file, _binary)
	
	//	I tried both shown lines, but none of them works
	application.showURL('file:///' + utils.stringReplace(_tmp_file, '\\', '/'), '_blank')	
	application.showURL('file:///' + _tmp_file, '_blank')

Am I doing somewthing wrong here? I expect a temporary file created on the local machine and then show it in the browser.

you are thinking wrong, a webclient DOES have access to somekind of folder on your server, but showURL does only have access in the webapss/root folder (and further)

Did you read my post above yours?
that’s the only way the SHOW the pdf immediatly (you need somekind of acrobat installed on windows)

It would be really a security issue to really open files directly from the web!!

Harjo,

I solved part of the problem by moving the files that I want to open somewhere under webapps/root folder, so that I can use the showUrl() to show the file directly from the server into the client browser.

But I still don’t understand, what you wrote before:

in webclient you can just do: plugins.file.writefile(‘myfile.pdf’, vBinaryData)

than the webclient does the rest for you, popup that file for you.

because I don’t see the webclient doing all the rest for me :cry:

In Servoy 5 the plugins.file.writeFile() method was changed so that it writes on the client (that is what I understood).
So that means that the following coding must work. I don’t see any reason why this shouldn’t work:

/**
 * @properties={typeid:35,uuid:"9E24DCA9-AE93-4B2C-AE1B-D2B4C56C0A80"}
 */
var _output = null;

/**
 * @properties={typeid:35,uuid:"FF41BA01-09B6-47D4-9173-ADB5B58BACD4"}
 */
var _server_path = 'D:\\Servoy_51\\application_server\\server\\webapps\\ROOT\\attachments\\globis\\35\\7\\4\\2\\7425E933-B28A-4539-A650-749D857B5D1B.pdf';

/**
 * @properties={typeid:24,uuid:"8AC21BAC-A82B-4900-9711-2F9E3C7E1F25"}
 */
function onShowDocument() 
{
   var _server = plugins.it2be_tools.server()

   _output = 'Get server object\n';
   _output += 'Read binary\n';     
   var _binary = _server.readFile(_server_path)
 
   if (! _binary)
   {
	_output += '... Failed\n';	  
      return;
   }
   
   _output += '... OK\n';	
   
   var _tmp_file = 'C:\\Temp\\myFile.pdf'
   var _tmp_file2 = 'myFile.pdf'
    	
   var _ok = plugins.file.writeFile(_tmp_file, _binary)
   _output += 'Binary file written to ' + _tmp_file + '\n';
   if (! _ok)
   {
  	 _output += '... Failed\n';	 
  	 return;
   }

   _output += '... OK\n';
   _output += '... Size = ' + _binary.length + '\n';
   
   _ok = plugins.file.writeFile(_tmp_file2, _binary)
   _output += 'Binary file written to ' + _tmp_file2 + '\n';
   if (! _ok)
   {
  	 _output += '... Failed\n';	 
  	 return;
   }

   _output += '... OK\n';
   _output += '... Size = ' + _binary.length + '\n';
   
   _output += 'Show in browser: ' + 'file:///' + utils.stringReplace(_tmp_file, '\\', '/') + '\n' 
   _ok = application.showURL('file:///' + utils.stringReplace(_tmp_file, '\\', '/'), '_blank')   
   if (! _ok)
   {
  	 _output += '... Failed\n';	 
  	 return;
   }

   _output += '... OK\n';   
   
   _output += 'Show in browser: ' + 'file:///' + utils.stringReplace(_tmp_file2, '\\', '/') + '\n' 
   _ok = application.showURL('file:///' + utils.stringReplace(_tmp_file2, '\\', '/'), '_blank')   
   if (! _ok)
   {
  	 _output += '... Failed\n';	 
  	 return;
   }

   _output += '... OK\n';   
}

The output shows the following:

Get server object
Read binary
... OK
Binary file written to C:\Temp\myFile.pdf
... OK
... Size = 467493
Binary file written to myFile.pdf
... OK
... Size = 467493
Show in browser: file:///C:/Temp/myFile.pdf
... OK
Show in browser: file:///myFile.pdf
... OK

And I don’t find the myFile.pdf on my client PC (not in Downloads directory, not in C:\Temp)
And there is not a new browser window shown (not even with message ‘file not found’)
I checked also my server directories. Also on the server in the C:\Temp directory I don’t find this file.

As far as I can see all this is correct Servoy javascript and I really don’t understand why this isn’t working.

FireFox, Safari (for windows) and Chrome show the same behavior
IE shows message about popup-window but no pdf file shown either. But there is a message about file not found (the file that is not in C:\Temp)
And there is not a single errormessage in the log on the adminpages.

I really don’t see what is wrong here :( :( :(
This is Servoy version 5.1.4 -build 964

It’s pretty simple

everything a webclient does with a file is ON the server!
so if your logs says: c:\TEMP, that is ON the server, 100%

your webrowser does not have access to your local c:\temp (ofcourse firefox en IE does have a temp folder for there cache)

BUT
if you test this on your developer (webclient started from developer) THAN c:\temp is the the temp-folder on your local c-drive.
you are than running server and webclient on the same machine.

EDIT:
and to workaround that all stuff in the webclient, servoy now helps you with that using: plugins.file.writefile(“test.pdf”, myBinaryData)
and streams that file from the server to your local webbrowser.

depending on your browser settings, you get download popup or (like in chrome) it downloads it immediatly to your browser-download folder.
that’s the way the web & browsers works!

hope this clears it more…

Harjo,

I agree that it worked like you describe, but that was in Servoy 4.x

The release notes of Servoy 5.1 mention the following: (https://wiki.servoy.com:8443/display/Serv51/Upgrade+Notes)

Behavior change

Using the writeFile function of the File plugin in the Web Client
Prior to 5.1, the syntax plugins.file.writeFile(null/String,…) would write the file serverside, in 5.1 and beyond it will trigger the streaming behavior to the browser as described in the Release Notes.

and also from this page: (https://wiki.servoy.com:8443/display/Serv51/newFeatureHighLights)

writeTXTFile, writeFile & writeXMLFile: When used in a Web Client and specifying null or a String for the file parameter, the file will be streamed to the browser. Depending on the browser settings, the browser will present the user with a File Open/Save dialog or will open the file directly in the appropriate application. When streaming the file to the browser, the file plugin will try to determine the type of file and set the content type accordingly, so the browser can recognize the type of file and open it with the appropriate application.

So it is not that clear and simple for me, because it doesn’t work like described above!

it is working, you said it yourself:

I’m afraid that is not working.
When I do what you wrote, the file is written to the User/Downloads directory.

that is exactly how it works…
plugins.file.writefile does not OPEN the file for you, it streams it to you

I have made some progress. Part of the problem I’ve been able to fix, but it is very dirty.

As you could see in my sample, you’ve seen the following:

:
var _server = plugins.it2be_tools.server()
var _binary = _server.readFile(_server_path)
var _ok = plugins.file.writeFile(_tmp_file, _binary)

_ok = application.showURL(‘file:///’ + utils.stringReplace(_tmp_file, ‘\’, ‘/’), ‘_blank’)
:

The dirty thing in this situation is, that the application.showURL() cancels all the statements that you see before.
So now it becomes clear to me that you must avoid to use application.showURL() in the webclient, unless you want to go to a certain page after logging off from Servoy.

Now I see in my downloads directory indeed the filename (when _tmp_file doesn’t have a path). If _tmp_file == null, then I see a file.bin appearing.

But still 2 things that are not clear:

  1. The application.showURL() should had created a new dialog. Why didn’t it create a new browser window instance?
  2. In your previous post you wrote “… webclient does the rest for you, popup that file for you.”. This popup is not working. Why?

martinh:
I have made some progress. Part of the problem I’ve been able to fix, but it is very dirty.

As you could see in my sample, you’ve seen the following:

:
var _server = plugins.it2be_tools.server()
var _binary = _server.readFile(_server_path)
var _ok = plugins.file.writeFile(_tmp_file, _binary)

indeed, in webclient, just stop here!!

_ok = application.showURL(‘file:///’ + utils.stringReplace(_tmp_file, ‘\’, ‘/’), ‘_blank’)
:

The dirty thing in this situation is, that the application.showURL() cancels all the statements that you see before.
So now it becomes clear to me that you must avoid to use application.showURL() in the webclient, unless you want to go to a certain page after logging off from Servoy.

Now I see in my downloads directory indeed the filename (when _tmp_file doesn’t have a path). If _tmp_file == null, then I see a file.bin appearing.

But still 2 things that are not clear:

  1. The application.showURL() should had created a new dialog. Why didn’t it create a new browser window instance?
  2. In your previous post you wrote “… webclient does the rest for you, popup that file for you.”. This popup is not working. Why?
  1. I don’t know how browsers handle the file:/// object. I never use that ( I think, file:/// only works in a browser, if the file is allready local!)
  2. that depends on your browser settings, for instance IE pops here popsup with a dialog, Do you want to open, or save this file. for ecample: Chrome directly downloads the file to his download folder.
    Look in both browser, to your settings:
    here you see mine of Firefox: (in Dutch)[attachment=0]Schermafbeelding 2010-11-19 om 14.55.29.png[/attachment]

Some more info:

In the following:

var _ok = plugins.file.writeFile(_tmp_file, _binary)

the variable _tmp_file can only contain a filename and not a full path in the webclient.
So myFile.pdf is allowed, but C:\Temp\myFile.pdf isn’t (it will try to save the file as C__Temp_myFile.pdf in my downloads directory)

And the line

_ok = application.showURL('file:///' + utils.stringReplace(_tmp_file, '\\', '/'), '_blank') 

will only create a new browser window when it is a http:// url, but not with a file:// url

And for me this explains also the problem that I have with the Jasper Report, where when running the report in webclient, that the option ‘view’ is not working, because it does exactly the same.
It streams the result of the Jasper Report to the browser and it tries to open the report in a new browser window using the file:/// url

So it looks like that when you want to show a Jasoer Report into the browser, that the binary report result (result from plugins.jasperPluginRMI.runReport()) that I have to do a writeFile myself so that the report is shown in a new window.

In my opinion it looks like there is a bug in the application.showURL(url, ‘_blank’) where this doesn’t work in all cases.
Can someone from Servoy confirm this?

martinh:
Some more info:

In the following:

var _ok = plugins.file.writeFile(_tmp_file, _binary)

the variable _tmp_file can only contain a filename and not a full path in the webclient.
So myFile.pdf is allowed, but C:\Temp\myFile.pdf isn’t (it will try to save the file as C__Temp_myFile.pdf in my downloads directory)

EXACTLY! :-)

And the line

_ok = application.showURL('file:///' + utils.stringReplace(_tmp_file, '\\', '/'), '_blank') 

will only create a new browser window when it is a http:// url, but not with a file:// url

EXACTLY! :-)

And for me this explains also the problem that I have with the Jasper Report, where when running the report in webclient, that the option ‘view’ is not working, because it does exactly the same.
It streams the result of the Jasper Report to the browser and it tries to open the report in a new browser window using the file:/// url

So it looks like that when you want to show a Jasoer Report into the browser, that the binary report result (result from plugins.jasperPluginRMI.runReport()) that I have to do a writeFile myself so that the report is shown in a new window.

In my opinion it looks like there is a bug in the application.showURL(url, ‘_blank’) where this doesn’t work in all cases.
Can someone from Servoy confirm this?

I think this has everything todo, with your browser setting en specifically your popupblockers!
set those off and try again!

Using file://…. doesn’t make sense in web-client. Because your solution is running in the browser from the app. server which is not local. When you try to show with showURL(…) it will try to open a new browser window on the client, not server, where the file://…. that exists on the server does not make sense (it would try to reference actual files in the client file system, not on the server file system). This assumes that the file://…. you are trying to show is really a file on the server.

If you are actually trying to open a file on the client, I doubt you know it’s location on the client file system in javascript running on the server. Even if you do (hard-coded or user inputs it in client browser) you still won’t be able to use it because the browser will see it as a dangerous attempt from some site to access a local file.

So the thing to do if needed in WC is either create the file on the server and serve it as a normal app. server link, or use Servoy defaults for doing this - media fields/plugin.file.write…

The following did the job for me.

There are two weird bits in it though that remain unclear to myself:

  1. When I copy a file with plugins.file.copyFile(origPath, destinationPath); then I can’t just make destinationPath = ‘/reports/reportName.pdf’. The file just does not appear in reports folder on server neither in ‘developer’ directory when running developer nor in application_server/server/webapps/root/reports when running a deployed solution. Only the absolute path to file works (and I get it by creating a dummy file in the server directory).

  2. application.getServerURL(); returns ‘localhost’ instead of a valid server url. Need to use the server IP and concatenate it with the port number.

	var path = generateReport(); //the function generates the pdf file on disk in a location external to the server and returns the path to the file
	
	var fileName = getFileName(); //this separates the file name from the path

	var tempFile = plugins.file.createFile("abrakadabra");
	var absServerPath = utils.stringReplace(tempFile.getAbsolutePath(), "abrakadabra", "");
	
	var copyFilePath = absServerPath + "\server\\webapps\\root\\webreports\\" + fileName;
	var success = plugins.file.copyFile(path, copyFilePath);
	
	var serverURL = application.getServerURL();
	application.showURL("http://" + plugins.it2be_tools.server().IP + utils.stringIndexReplace(serverURL, 1, utils.stringPosition(serverURL, ":", 1, 2), ":") + "/webreports/" + fileName);

Cheers,
Maria

Andrei Costescu:
Using file://…. doesn’t make sense in web-client. Because your solution is running in the browser from the app. server which is not local. When you try to show with showURL(…) it will try to open a new browser window on the client, not server, where the file://…. that exists on the server does not make sense (it would try to reference actual files in the client file system, not on the server file system). This assumes that the file://…. you are trying to show is really a file on the server.

If you are actually trying to open a file on the client, I doubt you know it’s location on the client file system in javascript running on the server. Even if you do (hard-coded or user inputs it in client browser) you still won’t be able to use it because the browser will see it as a dangerous attempt from some site to access a local file.

So the thing to do if needed in WC is either create the file on the server and serve it as a normal app. server link, or use Servoy defaults for doing this - media fields/plugin.file.write…

Andrei,

Could this also be the reason why the webclient doesn’t show my Jasper Report in a new browser window.
Because it looks like the Jasper Report is downloaded to the client, but Servoy probably doesn’t know where the report is placed, so it can’t open a new window with a file:// prefix

So shouldn’t the Jasper Report Plugin write the report result somewhere in a Temp directory within the application server\webapps\root directory (in case of a webclient), just like Maria showed in the above example, so that a new window can be opened?

Martin