【轉載】webwork上傳下載文件的問題總結

paul 14年前發布 | 5K 次閱讀 Web開發 文件打包工具 W3C

系統的架構是webwork+spring+hibernate,數據庫是SQLServer2000.

因為是第一次用webwork,所以也是到網上搜代碼搜例子,現在才發現baidu和google有些不一樣啊。

通過這幾天的baidu和google,發現網友們的筆記對我們來說真是重要啊,于是乎在做完了這些之后,也打算總結一下,一來讓自己把思路理順,二來方便大家用的到的時候直接粘貼。

先說說文件的上傳吧:

首先看xwork的配置文件;

<!-- 文檔上傳 -->
     <action name="uploadFileAction" class=".......action.UploadFileAction">
   
     <param name="rootPathKey">fileRoot</param>
           
            <result name="input" type="dispatcher">
                <param name="location">uploadDoc.jsp</param>
            </result>
            <interceptor-ref name="fileUpload">
             <param name="maximumSize">10485760</param>
            </interceptor-ref>
         <interceptor-ref name="params"/>
         <interceptor-ref name="autowireDefault"/>
    </action>

    第一個參數是我自己配在action里設置根目錄的一個key值,
    第三個是最重要的,就是那個maximumSize,他是用來設置webwork允許上傳的文件大小。
    不過根據試驗結果來看,他要和webwork.properties里的一個設置一起才能起作用,
  webwork.multipart.maxSize=10485760;
    這個要記得寫到webwork.properties里面來。

這下再來看看action的方法吧:

     action里重要的就是要設置屬性來接受這些webwork上傳上來的數據,

     這里面就有一個非常非常郁悶的問題了,就是在上傳的頁面里的那個input框的name屬性和這些變量是有關系的,

     比如在heml頁面的name=“docFile”, 那么在action里的接受上傳文件的file的名字就該設置為docFile,而接受文件類型的屬性就該設置為docFileContentType,千萬不要忘了get和set方法。
  
 <input name="docFile" type="file" class="textbox" id="docFile">

        private java.io.File docFile;

        private String docFileContentType;

之后就可以用這兩個變量來進行io操作了。


上傳比較簡單,做下載的時候可是碰到了一個大大的問題。

起初是在網上搜的代碼,也使用webwork設置的,xwork配置如下:

<!-- 文檔下載-->
 <action name="downloadFileAction" class="....action.DownloadFileAction">
     
       <result name="download" type="stream">
                 <param name="contentType">application/octet-stream</param>
                 <param name="inputName">docStream</param>
                 <param name="bufferSize">1024</param>             
                 <param name="contentDisposition">
   attachment;filename="${filename}"
    </param>
       </result>
           
          
            <interceptor-ref name="params"/>
            <interceptor-ref name="autowireDefault"/>
 </action>


然后action里是這么設置的:

 先要設置這幾個屬性,分別對應配置文件的不同參數:
  
 private InputStream docStream;
 
 private String contentType;
 
 private String contentDisposition;
 
 private int bufferSize;
 
 private String filename;

 然后將filename設置為我們需要的filename,在將一個inputstream賦給docStream,
然后return "download";

        起初這么做還可以,可是后來不知道怎么突然不行了,郁悶了半天,(寫這個的時候打算完了再試試這種方法。)一直報一個
ClientAbortException: java.net.SocketException: Connection reset by peer: socket write error的異常,而瀏覽器的動作就是突然打開準備下載的窗口又迅速消失了,我以為是我的瀏覽器設置的原因,就跑到同事那里試試,果不其然,通過了,happy中。

        可是下午測試時又出問題了,才發現是IE7的問題,在ie6上都沒有問題,于是開始懷疑webwork的下載。

        打算自己用response寫一個下載了。

        經過了測試,不行,還是原來的錯誤,于是道網上搜例子,看來看去還是和我的差不多,于是就變態的改header,改contenttype,改contentDisposition,反正是覺得那不順眼就改那里,還是不行。

        于是我把代碼直接貼到一個servlet里面,瀏覽器直接進入servlet,彈出下載框了。


        更加郁悶中。

        在郁悶中下班的時間來了,路上還在想是不是因為buffersize設的太小了,艾,遇到比較變態的問題時很多問題都不得不考慮,雖然現在想想是比較可笑的。

         今天早上來了一直在搜那個異常的信息,搜到的幾乎最全的答案就是這個:

         由于處理http連接時,正在輸出內容時,用戶關閉了IE,會出現一個個"ClientAbortException",屬于I/O處理中出現的一個異常,應用服務器應該會捕捉。
  Connection reset by peer的原因:
         經常出現的Connection reset by peer: 原因可能是多方面的,不過更常見的原因是:
         ①:服務器的并發連接數超過了其承載量,服務器會將其中一些連接Down掉;
         ②:客戶關掉了瀏覽器,而服務器還在給客戶端發送數據;
         ③:瀏覽器端按了Stop    

         加上由于在IE6里面通過了,我更懷疑是瀏覽器中止了流的輸出。


         最后終于有了一個讓我發現突破口的現象了,因為是在js里面用window.open指向action的,當我把昨天那個servlet寫到js里面是,竟然也出現了同樣的狀況,于是開始懷疑是提交action的方式不對才導致IE7出現這個錯誤的。于是我就又把這個servlet用
超鏈接的方式訪問了一下,沒問題。于是我想到了利用超鏈接的方式來訪問action的方法,ok。

        最后,終于在js里通過這樣的方式解決了一個IE7的下載bug。

        $("downloadhref").href = "downloadFileAction.action?fileId="+id[0];
        $("downloadhref").click();


最后在列上一個webwork文件下載時文件名亂碼的解決方法,也是在網上搜的,

        public String toUtf8String(String s) {
     StringBuffer sb = new StringBuffer();
     for (int i = 0; i < s.length(); i++) {
      char c = s.charAt(i);
      if (c >= 0 && c <= 255) {
       sb.append(c);
      } else {
       byte[] b;
       try {
        b = Character.toString(c).getBytes("utf-8");
       } catch (Exception ex) {
        System.out.println(ex);
        b = new byte[0];
       }
       for (int j = 0; j < b.length; j++) {
        int k = b[j];
        if (k < 0)
         k += 256;
        sb.append("%" + Integer.toHexString(k).toUpperCase());
       }
      }
     }
     return sb.toString();
  }

利用最原始的response的下載方式


  //文件下載
  HttpServletResponse response = ServletActionContext.getResponse();
  
  response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition","attachment;filename="+this.filename);

                //輸出流
  ServletOutputStream out = response.getOutputStream();
  //輸入流
  java.io.File f = new java.io.File(path);
  BufferedInputStream  in =  new BufferedInputStream(new FileInputStream(f));
  
  byte b[] = new byte[this.bufferSize];
  int bytesRead = 0;
  while ((bytesRead = in.read(b, 0 , this.bufferSize)) != -1)
  { 
   out.write(b, 0, bytesRead); //寫數據;
  }
  
  in.close();
  out.close(); 

---------------------------------------------------------------------------------
ie6下載后無法直接打開,緩存目錄excel文件不存在
 
若要解決此問題,請按照下列步驟操作:
  1. 單擊 開始、 單擊 運行,鍵入 %,然后單擊 確定
  2. 刪除 Temp 文件夾中的所有文件。
  3. 單擊 開始,然后單擊 控制面板
  4. 雙擊 Internet 選項
  5. 常規 選項卡上單擊 刪除文件,單擊以選中 刪除所有脫機內容 復選框,然后單擊 確定
  6. 在桌面上右鍵單擊 回收站 并單擊 清空回收站,然后單擊

參考 http://support.microsoft.com/kb/938200/zh-cn

 

 本文由用戶 paul 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!