Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
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 Go to next message
Bruno Sinou is currently offline Bruno SinouFriend
Messages: 22
Registered: December 2010
Location: Berlin
Junior Member
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 Confused .

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 Go to previous messageGo to next message
Bruno Sinou is currently offline Bruno SinouFriend
Messages: 22
Registered: December 2010
Location: Berlin
Junior Member
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 Go to previous messageGo to next message
Austin Riddle is currently offline Austin RiddleFriend
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 Go to previous messageGo to next message
Bruno Sinou is currently offline Bruno SinouFriend
Messages: 22
Registered: December 2010
Location: Berlin
Junior Member
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 #658554 is a reply to message #658489] Tue, 08 March 2011 23:24 Go to previous messageGo to next message
Austin Riddle is currently offline Austin RiddleFriend
Messages: 128
Registered: July 2009
Senior Member
Hi Bruno,

Quote:
1) if I understand your code correctly, you register a service for each file you want to publish, am I wrong ?


That is correct. When the users asks for the file, the handler is registered/created. A dialog is used to present the link. When the user closes the dialog after the download completes, the service is unregistered.
In your case of large filesets, if the access is not by users or is high frequency, then it is probably better to just set up an external fileserver for them.

Quote:
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 ?


We know the mime types ahead of time.

I hope this helps.
Re: Display or download files from server. [message #658714 is a reply to message #657553] Wed, 09 March 2011 15:29 Go to previous messageGo to next message
Bruno Sinou is currently offline Bruno SinouFriend
Messages: 22
Registered: December 2010
Location: Berlin
Junior Member
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 Go to previous messageGo to next message
Cole Markham is currently offline Cole MarkhamFriend
Messages: 150
Registered: July 2009
Location: College Station, TX
Senior Member

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 Go to previous message
Bruno Sinou is currently offline Bruno SinouFriend
Messages: 22
Registered: December 2010
Location: Berlin
Junior Member
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 ...
Previous Topic:[Table] Scrolling issue
Next Topic:RAP deployment on Weblogic fails
Goto Forum:
  


Current Time: Wed Oct 20 11:29:37 GMT 2021

Powered by FUDForum. Page generated in 0.01798 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top