2013-04-27 71 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