2013-04-27 73 views
0

我想编码一个简单的Struts2类来下载视频文件。除非我选择取消下载对话框中的下载,否则它工作正常,因为引发了java.lang.IllegalStateException(页面正常工作,异常被记录)。文件下载对话框中的IllegalStateException

下面是类:

public class FileDownloaderAction extends ActionSupport { 

/** The Constant serialVersionUID. */ 
private static final long serialVersionUID = 1L; 

/** The relative route to the file to download. */ 
private String relRoute; 

/** The name of the file to download. */ 
private String fileName; 

/** The InputStream to be downloaded. */ 
private InputStream fileStreamToDownload; 

/** The size of the file to download. */ 
private long fileSize; 

@Override 
public final String execute() throws Exception { 
    MyUtils mu = new MyUtils(); 

    try { 
     File file = mu.getFile(relRoute + fileName); 

     if (file != null) { 
      fileStreamToDownload = new FileInputStream(file); 
      fileSize = file.length(); 

      return Action.SUCCESS; 
     } else { 
      return Action.ERROR; 
     } 
    } catch (Exception ex) { 
     return Action.ERROR; 
    } 
} 

/** Sets the content disposition. 
* @return the content disposition. 
*/ 
public final String getContentDisposition() { 
    return "attachment;filename=\"" + fileName + "\""; 
} 

/** 
* @return the relRoute 
*/ 
public final String getRelRoute() { 
    return relRoute; 
} 

/** 
* @param mRelRoute the relRoute to set 
*/ 
public final void setRelRoute(final String mRelRoute) { 
    this.relRoute = mRelRoute; 
} 

/** 
* @return the fileStreamToDownload 
*/ 
public final InputStream getFileStreamToDownload() { 
    return fileStreamToDownload; 
} 

/** 
* @param mFileStreamToDownload the fileStreamToDownload to set 
*/ 
public final void setFileStreamToDownload(final InputStream mFileStreamToDownload) { 
    this.fileStreamToDownload = mFileStreamToDownload; 
} 

/** 
* @return the fileName 
*/ 
public final String getFileName() { 
    return fileName; 
} 

/** 
* @param mFileName the fileName to set 
*/ 
public final void setFileName(final String mFileName) { 
    this.fileName = mFileName; 
} 

/** 
* @return the fileSize 
*/ 
public final long getFileSize() { 
    return fileSize; 
} 

/** 
* @param mFileSize the fileSize to set 
*/ 
public final void setFileSize(final long mFileSize) { 
    this.fileSize = mFileSize; 
} 

}

在另一方面,在struts.xml中文件中定义的动作:

<action name="downloadFile" class="org.test.action.FileDownloaderAction" method="execute"> 
    <result name="success" type="stream"> 
     <param name="contentType">application/octet-stream</param> 
     <param name="inputName">fileStreamToDownload</param> 
     <param name="contentDisposition">${contentDisposition}</param> 
     <param name="contentLength">${fileSize}</param> 
     <param name="bufferSize">4096</param> 
     <param name="allowCaching">true</param> 
     <param name="contentCharSet">UTF-8</param> 
    </result> 
    <result name="error">/error.jsp</result> 
</action> 

该代码是基于我发现了一些例子。 Tomcat的打印这个时候抛出异常:

abr 28, 2013 12:11:59 AM org.apache.catalina.core.StandardWrapperValve 
invoke SEVERE: Servlet.service() para servlet default lanzó excepción java.lang.IllegalStateException 
at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:407) 
at org.apache.struts2.dispatcher.Dispatcher.sendError(Dispatcher.java:867) 
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:569) 
at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77) 
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) 
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) 
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) 
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) 
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) 
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298) 
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859) 
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588) 
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) 
at java.lang.Thread.run(Thread.java:722) 

是否有办法避免这种例外?

在此先感谢。

+0

当您点击取消按钮时,您是否发送任何服务器端请求? – 2013-04-28 07:43:17

+0

我不相信。正如@ dev-blanked写的,当我点击Cancel时,它发生在客户端,同时服务器不停地向我发送数据,所以发生异常。此外,[流结果页面](http://struts.apache.org/release/2.0.x/docs/stream-result.html)不会有太大的帮助... – dcordonu 2013-04-28 09:44:45

+0

@dcordonu你可以防止输出通知告知调度员不发送错误。无论如何,通过异常拦截器来处理异常是可能的。另见http://stackoverflow.com/questions/16213900/there-is-no-action-mapped-for-action-name-index-how-to-catch-the-exception-bec/16214532#16214532 – 2013-04-28 10:32:35

回答

0

当您将文件(在您的视频中)写入响应时,浏览器会显示保存/取消对话框。浏览器检测到这是一个文件并向用户提供文件保存对话框。当用户选择取消时,从浏览器到服务器的连接被取消,因此当服务器试图将文件的其余部分写入响应时,将记录此异常。我相信这种行为是有效的。由于取消操作完全发生在客户端(即浏览器内),因此您无法从服务器执行任何操作。

+0

好的,这是有道理的,但是,有没有办法来监视这个并避免异常被记录?或者,至少要编写自定义文本而不是完整的错误跟踪。 – dcordonu 2013-04-28 09:34:02

+0

@dcordonu以及相同的例外情况也可能出现在其他情况下。也许你可以记录下载视频操作已被调用。因此,当人们浏览日志并找到上面的堆栈跟踪并发现上面有一条说明视频下载被执行的日志时。可能可以得出结论,点击取消按钮 – 2013-04-28 09:41:16

+0

是的,你是对的。但是,如何检测到用户点击了“取消”按钮? – dcordonu 2013-04-28 09:52:19