How to send a file from a servlet the “right” way?

2019-02-15 14:04发布

问题:

I'm trying to send a file to a user from an http servlet. The servlet runs some identification tests (on the request) and then sends the client a file.

This generally works but now I turned on my TOMCAT server redirects to https and when I try to access the servlet and download the file from either IE6 or IE8 it fails and I get this exception:

java.lang.IllegalStateException: Cannot forward after response has been committed

(on the localhost.log)

and

ClientAbortException:  java.net.SocketException: Connection reset by peer: socket write error

(in the servlet log)

The code that does the sending (Simplified):

private void sendFile(HttpServletResponse response, byte[] file, String clientFileName)
{
    ServletOutputStream op = null;

    setContentType(response);
    response.setHeader("Content-Disposition", "attachment; filename=\"" + clientFileName + "\"");
    // send byte array to output buffer. 
    op = response.getOutputStream();

    // Content Length must be set after all processing done.
    response.setContentLength((int) file.length);   
    op.write(file);
}

Is this the correct way to send a file from a servlet? What's the best way?

Thanks!!

UPDATE

Used the code from @BalusC artice in this link: http://balusc.blogspot.com/2007/07/fileservlet.html

This made it work.

Still doesn't work in IE6-IE8 when used from Gmail because of a filtering stage gmail adds to downloads in these browsers.

UPDATE 2

The problem seems to be with Gmail + Internet Explorer 6-8. I'm Assuming that gmail is doing a redirect (That's actually pretty obvious if you look at the url on the page after you click the link in the mail). Is Client-Pull technique my only solution?

回答1:

The solution to the problem is the "Client-Pull" technique. By adding a Refresh value to the header we make the browser ask for the file.

This is the only solution I could come up to that overcomes the fact the gmail will use redirection when pressing a link from within an email.

In the code I did this:

response.setHeader("Refresh", "3; URL=\"" + url.toString() + "\"");
forwardToJSP(request, response, "waitForBrowserRefreshPage.jsp");

Meaning - after 3 seconds ask the user for the specified url which will, in turn, deliver the file to the client. The forwardToJSP method displays the "You will be forwarded soon, here a link if it fails" message.