简体   繁体   中英

best practice response.getOutputStream

any comments on my code on allowing user to download file.

if(fileObject !=null)
response.setHeader("Content-disposition", "attachment; filename=\""+fileObject.getFilename()+"\"");
response.setContentType(fileObject.getFiletype());
response.setContentLength((int)fileObject.getFilesize().intValue());
try {
 if(response !=null && response.getOutputStream() !=null &&fileObject!=null && fileObject.getBinData() !=null ){
    OutputStream out = response.getOutputStream();
    out.write(fileObject.getBinData());
 }


} catch (IOException e) {
    throw new ApplicationRuntimeException(e);
}

most of the time, i dont get below error. but once and a while, i get error

29 Nov 2010 10:50:41,925 WARN [http-2020-2] - Unable to present exception page: getOutputStream() has already been called for this response
java.lang.IllegalStateException: getOutputStream() has already been called for this response
 at org.apache.catalina.connector.Response.getWriter(Response.java:610)

The exception message is clear:

Unable to present exception page : getOutputStream() has already been called for this response
java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response. getWriter (Response.java:610)

An IOException was been thrown and you're rethrowing it as a custom exception which forced the servletcontainer to show the exception page which will use getWriter() for this. You should in fact let any IOException go because that's usually a point of no return.

An IOException can for example be thrown during the job when the client aborted the request. The best practice is to not catch IOException on the Servlet API yourself. It's already declared in throws clause of the servlet methods.

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    FileObject fileObject = getItSomehow();
    if (fileObject != null && fileObject.getBinData() != null) {
        response.setHeader("Content-disposition", "attachment; filename=\"" + fileObject.getFilename() + "\"");
        response.setContentType(fileObject.getFiletype());
        response.setContentLength((int)fileObject.getFilesize().intValue());
        response.getOutputStream().write(fileObject.getBinData());
    } else {
        // ???
    }
}

You are calling response.getOutputStream() twice. Instead, call it once and assign it to a local variable, then use that variable for your null check and your write operation.

try {
 OutputStream out = response.getOutputStream();
 if(response !=null && out !=null &&fileObject!=null && fileObject.getBinData() !=null ){
    out.write(fileObject.getBinData());
 }
} catch (IOException e) {
  throw new ApplicationRuntimeException(e);
}

How can response be null? Especially after you've already used it? Or response.getOutputStream()? Or fileObject, after you've already tested it for being non-null? And used it? These tests may be doing more harm than good.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM