MDA/MDD/TDD/DDD/DDDDDDD
          posts - 536, comments - 111, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          使用commons fileupload的零碎筆記

          Posted on 2007-08-27 11:58 leekiang 閱讀(30348) 評論(6)  編輯  收藏 所屬分類: fileupload
          我對表單上傳的理解(可能有誤):
          ?<form action="" method="post" enctype="multipart/form-data">
          ?最大上傳2G.
          通過 http 協議上傳文件(rfc1867協議概述,jsp 應用舉例,客戶端發送內容構造)
          ?服務器接收到上傳的流,自己其實是不作任何處理的,那個request還是原裝的,誰來處理這個request呢,一般采用第三方的工具,這里以commons fileupload為例.
          ?
          DiskFileItemFactory?factory?=?new?DiskFileItemFactory();
          factory.setSizeThreshold(
          4096);//?設置緩沖,這個值決定了是fileinputstream還是bytearrayinputstream
          factory.setRepository(new File("d:\\temp"));//設置臨時存放目錄,默認是new File(System.getProperty("java.io.tmpdir"))
          ServletFileUpload?sfu?=?new?ServletFileUpload(factory);
          sfu.setSizeMax(
          100*1024*1024);//100M
          List items?=?sfu.parseRequest(request);//傳入的這個request還是原裝的
          ?見上面的代碼,commons fielupload通過ServletFileUpload類的parseRequest(request)方法處理這個原始流。而ServletFileUpload又會調用其爺爺類FileUploadBase的parseRequest(request)方法,然后又會調return parseRequest(new ServletRequestContext(request)),代碼如下

          ????????
          try?{
          ????????????FileItemIterator?iter?
          =?getItemIterator(ctx);
          ????????????List?items?
          =?new?ArrayList();
          ????????????FileItemFactory?fac?
          =?getFileItemFactory();
          ????????????
          if?(fac?==?null)?{
          ????????????????
          throw?new?NullPointerException(
          ????????????????????
          "No?FileItemFactory?has?been?set.");
          ????????????}
          ????????????
          while?(iter.hasNext())?{
          ????????????????FileItemStream?item?
          =?iter.next();
          ????????????????FileItem?fileItem?
          =?fac.createItem(item.getFieldName(),
          ????????????????????????item.getContentType(),?item.isFormField(),
          ????????????????????????item.getName());
          ????????????????
          try?{
          ????????????????????Streams.copy(item.openStream(),?fileItem.getOutputStream(),
          ????????????????????????????
          true);
          ????????????????}?
          catch?(FileUploadIOException?e)?{
          ????????????????????
          throw?(FileUploadException)?e.getCause();
          ????????????????}?
          catch?(IOException?e)?{
          ????????????????????
          throw?new?IOFileUploadException(//報錯經常在這里
          ????????????????????????????
          "Processing?of?"?+?MULTIPART_FORM_DATA
          ????????????????????????????
          +?"?request?failed.?"?+?e.getMessage(),?e);
          ????????????????}
          ????????????????
          if?(fileItem?instanceof?FileItemHeadersSupport)?{
          ????????????????????
          final?FileItemHeaders?fih?=?item.getHeaders();
          ????????????????????((FileItemHeadersSupport)?fileItem).setHeaders(fih);
          ????????????????}
          ????????????????items.add(fileItem);
          ????????????}
          ????????????
          return?items;
          ????????}?
          catch?(FileUploadIOException?e)?{
          ????????????
          throw?(FileUploadException)?e.getCause();
          ????????}?
          catch?(IOException?e)?{
          ????????????
          throw?new?FileUploadException(e.getMessage(),?e);
          ????????}
          ????

          ?這里注意,上傳的<input type=file
          >標記一定要有name,如果沒有,commons fielupload不作處理
          ?commons fielupload會把上傳的文件以流的方式寫入到temp文件夾,臨時文件夾可以自己設定,如果不手動設置,則是Servlet容器為web應用分配的臨時目錄,tomcat可能就是%TOMCAT_HOME%\temp,我用weblogic時,是C:\DOCUME~1\yourname\LOCALS~1\Temp\。這些臨時文件以"upload"開頭,格式是.tmp,例如"upload_47fdc3_11c9eb678b0__8000_00000043.tmp"
          ?在上傳過程中commons fielupload才知道上傳的文件的大小,如果你定義允許的最大附件為100M,然后你上傳一個200M的文件,那么只有實際傳輸了100M以后,commons fielupload才知道超過了,然后拋出一個異常(org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException)。
          ?commons fielupload處理完了以后(處理過程全在parseRequest(request)方法里),返回一個List,里面的每一項已被封裝為FileItem,你通過fileItem.isFormField()判斷出是普通的表單屬性呢,還是一個文件,如果是文件,你可以從fileItem.getInputStream()獲得輸入流,這個輸入流其實是一個FileInputStream.當然,如果文件很小,則是ByteArrayInputStream.那么如何區分?這兩者的區別是由factory.setSizeThreshold(4096)確定的。大于4K,為FileInputStream,小于4K為ByteArrayInputStream

          這樣就可以解釋struts用ActionForm的方式處理上傳附件的一些問題了,struts接收到enctype="multipart/form-data"的post請求后,會看那個對應的action有沒有配置actionform,如果配置了,就會作一些處理,所以你在action里得到的request已經不是一個普通的request了,而是一個被封裝過的request。如果想得到原始的request,就不要struts-config.xml里給action類配置actionform

          tempDir指定的目錄中可能會隨著時間推移出現很多后綴為"tmp"的垃圾文件,commons-fileupload1.2提供了一個不錯的解決方法,就是把下面的代碼加入到web.xml中即可。
          <listener>
          <listener-class>
          org.apache.commons.fileupload.servlet.FileCleanerCleanup
          </listener-class>
          </listener>
          來源:http://fratemity1314.spaces.live.com/Blog/cns!E3BCC13A1E72BB4F!222.entry

          Q:I'm using FileUpload in an Action, but it's not working. Why?

          A:Struts recognises multipart requests, and parses them automatically, presenting the request parameters to your code in the same manner as if they were regular request parameters. Since struts has already processed the request, and made it available in your form bean, the input stream is no longer available for parsing, so attempting to do so with FileUpload will fail.

          Q:But I need to parse the request myself. How can I do that?

          A:Struts parses multipart a request as a part of the process of populating your form bean from that request. If, for some reason, you need to have full control over the multipart parsing, you can do so by configuring your action mapping without an associated form bean. (A better way of doing this, however, is to replace the default multipart handler with your own. See the struts documentation for details.)



          1,直接用commons fileupload而不用struts的ActionForm時,表單里的屬性值不能用request.getParameter()獲取了,而url里的queryString可以。
          2,? 獲取form里的屬性值的代碼


          ????????????????????String?formname?
          =?fi.getFieldName();//?獲取form中的名字
          ????????????????????String?formcontent?=?fi.getString();
          ????????????????????
          if?(formname.equals("id"))?{
          ????????????????????????id?
          =?formcontent;
          ????????????????????}
          ?else?if?(formname.equals("title"))?{
          ????????????????????????title?
          =?formcontent;
          ????????????????????}
          ?else?if?(formname.equals("memo"))?{
          ????????????????????????memo?
          =?formcontent;
          ????????????????????}

          ????????????????

          3, 表單里的file控件的name不能為空。
          4,上傳大文件(190多M)時報異常
          org.apache.commons.fileupload.FileUploadException: ? Processing ? of ? multipart/form-data ? request ? failed. ? EOF ? after ? reading ? only: ? "3567789 " ? of: ? "203323339 " ? promised ? bytes, ? out? of ? which ? at ? least: ? "0 " ? were ? already ? buffered
          http://forums.bea.com/thread.jspa?threadID=200033356
          http://dev2dev.bea.com.cn/bbs/thread.jspa?forumID=121&threadID=20060&start=0&tstart=0
          http://thisisxy.blogcn.com/diary,204014352.shtml
          http://www.80diy.com/home/20050527/17/4040711.html

          5,
          org.apache.commons.fileupload.FileUploadException: Processing of multipart/form-data request failed. Read timed out
          HTTP活動超時限制的時間太短 HTTP Keep-Alive Timeout.

          6,InputStream is =formFile.getInputStream() ;? //formFile是org.apache.struts.upload.FormFile
          上傳的文件小時這個輸入流是java.io.ByteArrayInputStream,上傳比較大的文件時這個輸入流是FileInputStream

          7,設置表單里的上傳路徑為只讀
          <input type=file id="uploadfile" name="uploadfile" style="display: none;">
          <input type=text id=tempfile readonly="true">
          <input type=button
          onClick="uploadfile.click();tempfile.value=uploadfile.value;" value="瀏覽..">

          10,
          http://eastpoint.javaeye.com/blog/99084
          http://topic.csdn.net/u/20080131/13/649c57c7-204e-4bb6-9b09-49cca39f00b8.html
          http://blog.niwota.com/nb/chenchuang?cat_self_id=291075

          評論

          # re: 使用commons fileupload的零碎筆記  回復  更多評論   

          2008-10-31 15:27 by leekiang
          對于post和get的參數,好像commons fileupload的處理是不一樣的,get參數可以直接通過request.getParameter()的方式獲取,而post的不行,待驗證。

          # re: 使用commons fileupload的零碎筆記  回復  更多評論   

          2009-07-23 10:24 by 尹偉杰
          我現在就遇到了這樣的問題

          # re: 使用commons fileupload的零碎筆記  回復  更多評論   

          2009-07-23 10:27 by 尹偉杰
          一次性上傳衛星照片4個 大于2G weblogic報錯 超時 但是 改成4個form分開
          一個form 965m 也報錯 都暈了,你當時是怎么解決的???
          我的qq是838303967

          # re: 使用commons fileupload的零碎筆記  回復  更多評論   

          2009-07-23 10:29 by 尹偉杰
          Processing of multipart/form-data request failed. EOF after reading only: '38535168' of: '967898783' promised bytes, out of which at least: '0' were already buffered 報的錯!!!

          # re: 使用commons fileupload的零碎筆記  回復  更多評論   

          2009-07-28 18:49 by 尹偉杰
          哥們你趕快上線啊!!我的快瘋了!!!我的電話是13146277259 qq是838303967!!!

          # re: 使用commons fileupload的零碎筆記  回復  更多評論   

          2010-08-30 21:58 by gogoes
          throw new IOFileUploadException(//報錯經常在這里
          "Processing of " + MULTIPART_FORM_DATA
          + " request failed. " + e.getMessage(), e);


          我現在處理大量用戶數據時,老是這里出錯,出錯信息如下:
          Caused by: org.apache.commons.fileupload.FileUploadException: Processing of multipart/form-data request failed. Stream ended unexpectedly
          at com.alibaba.service.upload.patch.ServletFileUpload.parseRequest(ServletFileUpload.java:162)
          at com.alibaba.service.upload.patch.ServletFileUpload.parseRequest(ServletFileUpload.java:40)
          at com.alibaba.service.upload.DefaultUploadService.parseRequest(DefaultUploadService.java:165)

          能幫看看,有什么解決的辦法嗎?
          主站蜘蛛池模板: 九江县| 嘉黎县| 霍林郭勒市| 大新县| 台南县| 临湘市| 兰州市| 玉龙| 遵化市| 霍城县| 满城县| 江永县| 偃师市| 定日县| 邛崃市| 奉新县| 额尔古纳市| 贞丰县| 云南省| 德兴市| 东平县| 龙江县| 新营市| 双峰县| 呼和浩特市| 夏津县| 衡水市| 怀集县| 循化| 雅安市| 平湖市| 南华县| 怀远县| 沅陵县| 班戈县| 于田县| 塘沽区| 大化| 镇巴县| 甘孜县| 南岸区|