Technically, you never "download a file", because HTTP is not a file server, it's a WEB server. Web servers can present content in response to the client request. What the client does with that returned content is actually totally up to the client. One thing you can never do iis "download to the user's download folder:. The closest that you can get is that the client has selected a folder that will serve as a destination for received content that the client wishes to save into a file.
Confused? There's more! There's a set of MIME rules for the client that clients typically use to determine what to do with what they've received. These rules are usually customizable, in fact. By default, for example, content-type text/html (as indicated by the HTTP Content-Type header) will be rendered as a page in the user's web browser. But depending on the user's setup, content-type text/text may either get opened as a vanilla page in the browser or may cause something like the Windows Notepad to get launched to display the text. At one time, content-type x-vnd/xls would cause an Excel spreadsheet to open in the browser as an OLE embedded object, but Microsoft got sued for patent infringement, so they had to change things so that Excel got opened as a stand-alone application instead.
Then there's the Content-Disposition header which can be used to indicate that instead of using the "open" option indicated for the MIME type in question, that the content should be saved as a file with the name suggested on the header.
In other words, it will do what you want done (by default). Except when it doesn't. And the server has no control over that, so you're in the same situation as everyone else who ever did something like that and the users will see the same things they're already used to seeing. It's just that there's no Final Answer, is all.
On the server side you can generate content either on the fly (straight to the HttpServletResponse outputstream) or you can (as you indicated you wanted to do) generate the content to a file, then copy that file to the response outputstream. The advantages of the second, more indirect approach is that it doesn't eat up as much RAM (is more scaleable) and you will definitively know what Content Size to put in the response header. Plus you can generate additional headers if needed based on your file create processing. Something that you cannot do once the content body starts going out on the response.
As it happens, the java.io.File class has a "tempfile" capability that will create and open temporary files for you. It's a good place to write stuff like that to, and there's even an auto-deletion feature that gets rid of the file once you're done with it. The actual location of the tempfile is determined by the JVM, although many webapp servers set a specific location by default (for example,
Tomcat will create them in TOMCAT_HOME/temp unless you configure an alternate location for them.
So:
1. Create a tempfile using the java.io.File facilities
2. Construct the XLS content, writing it out to that tempfile.
3. Copy that tempfile's contents (with appropriate HTTP headers) to the HttpServletResponse outputstream
4. Bob's your uncle. At that point, it's the user who has to figure out what to do with it. Make sure that either automatically or manually you delete the server's tempfile, though, so that you don't slowly fill up the server's disks.