GWT RPC services can only send Java objects to the client. To send the file back to the user, you need to use a non-GWT Java servlet. Here is some code that I used before to serve jpeg images from the repository.
public class ImageServlet extends HttpServlet { private final String repository = "/var/images/"; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String filename = request.getParameter("file"); // Security: '..' in the filename will let sneaky users access files // not in your repository. filename = filename.replace("..", ""); File file = new File(repository + filename); if (!file.exists()) throw new FileNotFoundException(file.getAbsolutePath()); response.setHeader("Content-Type", "image/jpeg"); response.setHeader("Content-Length", String.valueOf(file.length())); response.setHeader("Content-disposition", "attachment;filename=\"" + filename + "\""); BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream()); byte[] buf = new byte[1024]; while (true) { int length = bis.read(buf); if (length == -1) break; bos.write(buf, 0, length); } bos.flush(); bos.close(); bis.close(); } }
"Content-disposition: attachment" should make most browsers download the file rather than displaying it, and the default file name does not depend on what you provide. The way to use this servlet is for the user to call the RPCService that you already have, which saves the file in the repository folder. You then link or redirect them to this servlet with a URL, for example http://your.domain.com/fileServlet?file=myFile.jpg . Obviously, with this setting, you have a security risk when users can upload other people's files if they can guess the file names.
What you might like is to combine the database code from your RPC service into this servlet. There is no need to save the file anywhere in the server, you can take the results of your database and write them to response.getOutputStream () or response.getWriter () just like you write them to a file, except that the result is directly to to the user. As long as you set the content headers correctly, the user will not notice the difference.
You cannot call this method from another servlet, the only way to force the browser to load it as a file is to access it through a regular HTTP request. First, you declare the servlet in the web.xml file, as if you were using the RPC GWT service:
<servlet> <servlet-name>ImageServlet</servlet-name> <servlet-class> com.package.ImageServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>ImageServlet</servlet-name> <url-pattern>/imageServlet</url-pattern> </servlet-mapping>
Now, any HTTP GET requests sent by http: //your.tomcat.server/webapp/imageServlet will be received by ImageServlet.doGet (). Then on the client side you can either make a normal html link to the file:
new HTML("<a href='" + GWT.getHostPageBaseURL() + "imageServlet?file=" + filename + "'>download</a>");
... or, you should be able to put this in a ClickHandler (I haven't tested it):
Window.Location.assign(GWT.getHostPageBaseURL() + "imageServlet?file=" + filename);