Home » Eclipse Projects » Remote Application Platform (RAP) » Display or download files from server.(The browser attemps to display the file within the browser instead of opening a Dialog to choose between opening or saving the file.)
Display or download files from server. [message #657553] |
Thu, 03 March 2011 09:27 |
|
Hello All.
In rap 1.3.1, following the example found here http://wiki.eclipse.org/RAP/FAQ#How_to_provide_download_link .3F , I'm trying to implement an object that would enable the user to get a file from the server and either open it in a system editor or save it on the local file system.
I must have missed something because, even when I hard code the content type to "application/pdf" for instance while trying to get a pdf file, the browser (FireFox 3.6 on CentOS 5.5) attempts to directly display it and it results to an error :
Could not evaluate javascript response:
SyntaxError: syntax error
%PDF-1.4
...
Normally, while browsing the net, when I click on a link to a pdf file (http://www.samplepdf.com/sample.pdf for instance), I get a dialog box that ask me weither I want to download it or open it with my system editor.
I would like to have the same behaviour within my app.
Here is the code I use to begin with and understand the process :
...
HttpServletResponse response = RWT.getResponse();
response.setContentType("application/pdf");
byte[] ba = null;
ba = FileUtils.readFileToByteArray(tmpFile);
response.setContentLength(ba.length);
String contentDisposition = "attachment; filename=\"" + fileName + "\"";
response.setHeader("Content-Disposition", contentDisposition);
response.getOutputStream().write(ba);
I'm sorry if my question is trivial but I have encountered pbs trying searching the net with both "download" or "display" key words .
Thanks for your help.
Bruno
[Updated on: Thu, 03 March 2011 09:49] Report message to a moderator
|
|
|
Re: Display or download files from server. [message #657954 is a reply to message #657553] |
Fri, 04 March 2011 17:38 |
|
Hello again,
I've gone further with my investigations and tried to force the opening of the download dialog on the client browser side adding some properties I've found on the web to the servletResponse header like the followings :
String contentDisposition = "attachment; filename=\"" + fileName + "\"";
response.setContentType("application/force-download");
response.setHeader("Content-Disposition", contentDisposition);
response.setHeader("Content-Transfer-Encoding", "binary");
esponse.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache, must-revalidate");
But I still get the same error :
Could not evaluate javascript response:
SyntaxError: illegal character
I'm quite stuck. I tried to debug in the RAP code but I couldn't figure out where the translation of the stream to javascript is done by rap. I wonder if there is a way to prevent it or if there is a known workaround.
Hope someone can help.
Kind regards.
Bruno
|
|
|
Re: Display or download files from server. [message #657975 is a reply to message #657954] |
Fri, 04 March 2011 18:53 |
Austin Riddle Messages: 128 Registered: July 2009 |
Senior Member |
|
|
Hi Sinou,
I see you have tried:
response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
This works in our code.
Here is the download handler that we use:
public class DownloadHandler implements IServiceHandler
{
private File srcFile;
private URI bundleFile;
private String clientName;
private String contentType;
private String id;
private DownloadHandler(String id, String contentType, String clientFileName)
{
this.id = id.replaceAll("\\s", "%20");
this.clientName = clientFileName;
this.contentType = contentType;
RWT.getServiceManager().registerServiceHandler(id+hashCode(), this);
}
public DownloadHandler(String id, File wbFile, String contentType, String clientFileName)
{
this(id, contentType, clientFileName);
this.srcFile = wbFile;
}
public DownloadHandler(String id, URI bundleFile, String contentType, String clientFileName)
{
this(id, contentType, clientFileName);
this.bundleFile = bundleFile;
}
public String getURL()
{
StringBuffer url = new StringBuffer();
url.append(URLHelper.getURLString(false));
url.append("?");
url.append(IServiceHandler.REQUEST_PARAM);
url.append("=" + id+hashCode());
return ContextProvider.getResponse().encodeURL(url.toString());
}
public void service() throws IOException, ServletException
{
HttpServletResponse response = ContextProvider.getResponse();
response.setContentType(contentType);
if (Boolean.valueOf(ContextProvider.getRequest().getParameter("attachment"))) {
response.setHeader("Content-Disposition", "attachment;filename=\"" + clientName + "\"");
}
ServletOutputStream outStream = response.getOutputStream();
InputStream srcStream = null;
if (srcFile != null) {
srcStream = new FileInputStream(srcFile);
if (srcFile.length() < Integer.MAX_VALUE) {
response.setContentLength((int)srcFile.length());
}
}
else if (bundleFile != null) {
srcStream = bundleFile.toURL().openStream();
}
try {
byte[] content = new byte[1024];
int bytesRead = 0;
while ((bytesRead = srcStream.read(content)) > 0) {
outStream.write(content, 0, bytesRead);
}
} catch (IOException e) {
Logger.alert(e.toString());
} finally {
srcStream.close();
}
}
public void dispose()
{
RWT.getServiceManager().unregisterServiceHandler(id+hashCode());
}
}
[Updated on: Fri, 04 March 2011 18:58] Report message to a moderator
|
|
|
Re: Display or download files from server. [message #658489 is a reply to message #657975] |
Tue, 08 March 2011 17:42 |
|
Hello Austin,
Many thanks for the reply, i'm going to try it right now.
Meanwhile I have 2 questions :
1) if I understand your code correctly, you register a service for each file you want to publish, am I wrong ?
To speak a little bit more about the context, I'm working on a distant file repository based on an implementation of JCR with a large amount of files, so it does not fit to register all of them.
Do you think that I will have to create and register a new service each time I want to download a file and then ensure to dispose it once the download is over ?
2) handling of the content type is outside the scope of your implemented service. In your case, who is dealing with it ? Is it directly stored in your file system or do you have a kind of mapping between file extension and mimeType ?
Many thanks for the help.
With kind regards
bruno
|
|
| |
Re: Display or download files from server. [message #658714 is a reply to message #657553] |
Wed, 09 March 2011 15:29 |
|
OK; thanks again for the quick answer.
So finally I managed to implement a service handler that have the required behaviour : I have started from scratch with a view displaying a org.eclipse.swt.Browser object with the well formatted URL and the view display a link that trigger the opening of the download dialog.
But my point is to open/download that file through a DoubleClickListenner bound to some cell in a Jface treeViewer and I'm still stuck at this point.
Can someone help me with that ?
How is it possible to have the same behaviour as clicking on a Browser object while triggering DoubleClickEvent on a treeViewer ? (for the moment, we can consider that we always open the same file with only one URL and only one service handler : fine tuning the opening of various files should not be a pb afterwhile.)
I go on searching on my side and I will post the full answer as soon as I manage to have it works.
Many thanks by advance.
Bruno
|
|
|
Re: Display or download files from server. [message #658804 is a reply to message #658714] |
Wed, 09 March 2011 20:37 |
|
Bruno,
We have a similar interaction in our system. Users can either right-click and select an menu item or double-click to download a file. We wrapped this functionality up into a "DownloadDialog" which creates a hidden dialog with a Browser widget (corresponding to an iframe on the client), and sets the URL of the download handler into it. The download handler specifies the Content-Disposition HTTP header to tell the user's browser the file should be downloaded.
This works well in most cases, but Internet Explorer's default settings block javascript-initiated file downloads (which is what ultimately happens). When this happens the user is presented the "information bar" which slides down from the top of the browser. Unless their security settings prevent it, they can choose to always allow downloads from your website. This will cause the page to reload which will restart the workbench and they will probably have to find their way back to where they were. They should only have to do this once though. I think there are ways to lock IE down so users cannot change this setting, so it may not work for all users if they are in a restricted environment.
This issue with IE is the reason that the recommended way is to have a link the user must click. If you are ok with the caveats, then you can make it work with a double-click in a viewer.
I have included the source for both the DownloadDialog and DownloadHandler we use below.
Hope this helps,
Cole
DownloadDialog:
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
public class DownloadDialog extends Dialog {
Browser b;
String url;
public DownloadDialog(Shell parent) {
super(parent);
}
public void setURL (String url) {
if (b != null && !b.isDisposed()) {
b.setUrl(url);
}
this.url = url;
}
@Override
protected Control createDialogArea(Composite parent) {
Control control = super.createDialogArea(parent);
b = new Browser(parent, SWT.NONE);
if (url != null) {
b.setUrl(url);
}
return control;
}
@Override
protected Control createButtonBar(Composite parent) {
return null;
}
@Override
protected int getShellStyle() {
return SWT.NO_TRIM;
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setSize(1, 1);
newShell.setMinimized(true);
}
}
DownloadHandler:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.rwt.RWT;
import org.eclipse.rwt.internal.service.ContextProvider;
import org.eclipse.rwt.internal.util.URLHelper;
import org.eclipse.rwt.service.IServiceHandler;
public class DownloadHandler implements IServiceHandler
{
private File srcFile;
private URI bundleFile;
private String clientName;
private String contentType;
private String id;
private DownloadHandler(String id, String contentType, String clientFileName)
{
this.id = id.replaceAll("\\s", "%20");
this.clientName = clientFileName;
this.contentType = contentType;
RWT.getServiceManager().registerServiceHandler(id+hashCode(), this);
}
public DownloadHandler(String id, File wbFile, String contentType, String clientFileName)
{
this(id, contentType, clientFileName);
this.srcFile = wbFile;
}
public DownloadHandler(String id, URI bundleFile, String contentType, String clientFileName)
{
this(id, contentType, clientFileName);
this.bundleFile = bundleFile;
}
public String getURL()
{
StringBuffer url = new StringBuffer();
url.append(URLHelper.getURLString(false));
url.append("?");
url.append(IServiceHandler.REQUEST_PARAM);
url.append("=" + id+hashCode());
return ContextProvider.getResponse().encodeURL(url.toString());
}
public void service() throws IOException, ServletException
{
HttpServletResponse response = ContextProvider.getResponse();
response.setContentType(contentType);
if (Boolean.valueOf(ContextProvider.getRequest().getParameter("attachment"))) {
response.setHeader("Content-Disposition", "attachment;filename=\"" + clientName + "\"");
}
ServletOutputStream outStream = response.getOutputStream();
InputStream srcStream = null;
if (srcFile != null) {
srcStream = new FileInputStream(srcFile);
if (srcFile.length() < Integer.MAX_VALUE) {
response.setContentLength((int)srcFile.length());
}
}
else if (bundleFile != null) {
srcStream = bundleFile.toURL().openStream();
}
try {
byte[] content = new byte[1024];
int bytesRead = 0;
while ((bytesRead = srcStream.read(content)) > 0) {
outStream.write(content, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
srcStream.close();
}
}
public void dispose()
{
RWT.getServiceManager().unregisterServiceHandler(id+hashCode());
}
}
|
|
|
Re: Display or download files from server. [message #658822 is a reply to message #658804] |
Wed, 09 March 2011 22:33 |
|
Thanks a lot Cole.
On my side I finally achieve it quite simply adding the following snippet in my double click listener
URL url = new URL(createFullDownloadUrl(fileName, fileId));
PlatformUI.getWorkbench().getBrowserSupport().createBrowser("DownloadDialog").openURL(url);
...
private String createFullDownloadUrl(String fileName, String fileId) {
StringBuilder url = new StringBuilder();
url.append(RWT.getRequest().getRequestURL());
url.append(createParamUrl(fileName, fileId));
return url.toString();
}
private String createParamUrl(String filename, String fileId) {
StringBuilder url = new StringBuilder();
url.append("?");
url.append(IServiceHandler.REQUEST_PARAM);
url.append("=downloadServiceHandler");
url.append("&filename=");
url.append(filename);
url.append("&fileid=");
url.append(fileId);
String encodedURL = RWT.getResponse().encodeURL(url.toString());
return encodedURL;
}
the only trick is that I have only one serviceandler that must have a reference to some file provider to recover file from Ids.
Anyway, I then fall against a problem very similar to yours : the dialog box is open in a new "pop up" browser that is blocked by default...
But I consider my problem as solved for now, I will try to find a workaround maybe later on.
I'll try to post the full code soon if it can help someone else, but not tonight ...
|
|
|
Goto Forum:
Current Time: Fri Mar 29 06:31:29 GMT 2024
Powered by FUDForum. Page generated in 0.03283 seconds
|