我對(duì)表單上傳的理解(可能有誤):
?<form action="" method="post" enctype="multipart/form-data">
?最大上傳2G.
通過(guò) http 協(xié)議上傳文件(rfc1867協(xié)議概述,jsp 應(yīng)用舉例,客戶(hù)端發(fā)送內(nèi)容構(gòu)造)?服務(wù)器接收到上傳的流,自己其實(shí)是不作任何處理的,那個(gè)request還是原裝的,誰(shuí)來(lái)處理這個(gè)request呢,一般采用第三方的工具,這里以commons fileupload為例.
?
DiskFileItemFactory?factory?=?new?DiskFileItemFactory();
factory.setSizeThreshold(4096);//?設(shè)置緩沖,這個(gè)值決定了是fileinputstream還是bytearrayinputstream
factory.setRepository(new File("d:\\temp"));//設(shè)置臨時(shí)存放目錄,默認(rèn)是new File(System.getProperty("java.io.tmpdir"))
ServletFileUpload?sfu?=?new?ServletFileUpload(factory);
sfu.setSizeMax(100*1024*1024);//100M
List items?=?sfu.parseRequest(request);//傳入的這個(gè)request還是原裝的
?見(jiàn)上面的代碼,commons fielupload通過(guò)ServletFileUpload類(lèi)的
parseRequest(request)方法處理這個(gè)原始流。而ServletFileUpload
又會(huì)調(diào)用其爺爺類(lèi)FileUploadBase的parseRequest(request)方法,然后又會(huì)調(diào)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(//報(bào)錯(cuò)經(jīng)常在這里
????????????????????????????"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>標(biāo)記一定要有name,如果沒(méi)有,commons fielupload不作處理。
?commons fielupload會(huì)把上傳的文件以流的方式寫(xiě)入到temp文件夾,臨時(shí)文件夾可以自己設(shè)定,如果不手動(dòng)設(shè)置,則是Servlet容器為web應(yīng)用分配的臨時(shí)目錄,tomcat可能就是
%TOMCAT_HOME%\temp,我用weblogic時(shí),是
C:\DOCUME~1\yourname\LOCALS~1\Temp\。這些臨時(shí)文件以"upload"開(kāi)頭,格式是.tmp,例如
"upload_47fdc3_11c9eb678b0__8000_00000043.tmp"?在上傳過(guò)程中commons fielupload才知道上傳的文件的大小,如果你定義允許的最大附件為100M,然后你上傳一個(gè)200M的文件,那么只有實(shí)際傳輸了100M以后,commons fielupload才知道超過(guò)了,然后拋出一個(gè)異常(
org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException)。
?commons fielupload處理完了以后(處理過(guò)程全在
parseRequest(request)方法里),返回一個(gè)List,里面的每一項(xiàng)已被封裝為FileItem,你通過(guò)
fileItem.isFormField()判斷出是普通的表單屬性呢,還是一個(gè)文件,如果是文件,你可以從
fileItem.getInputStream()獲得輸入流,這個(gè)輸入流其實(shí)是一個(gè)FileInputStream.當(dāng)然,如果文件很小,則是ByteArrayInputStream.那么如何區(qū)分?這兩者的區(qū)別是由
factory.setSizeThreshold(4096)確定的。大于4K,為FileInputStream,小于4K為ByteArrayInputStream
這樣就可以解釋struts用ActionForm的方式處理上傳附件的一些問(wèn)題了,struts接收到enctype="multipart/form-data"的post請(qǐng)求后,會(huì)看那個(gè)對(duì)應(yīng)的action有沒(méi)有配置actionform,如果配置了,就會(huì)作一些處理,所以你在action里得到的request已經(jīng)不是一個(gè)普通的request了,而是一個(gè)被封裝過(guò)的request。如果想得到原始的request,就不要struts-config.xml里給action類(lèi)配置actionform
tempDir指定的目錄中可能會(huì)隨著時(shí)間推移出現(xiàn)很多后綴為"tmp"的垃圾文件,commons-fileupload1.2提供了一個(gè)不錯(cuò)的解決方法,就是把下面的代碼加入到web.xml中即可。
<listener>
<listener-class>
org.apache.commons.fileupload.servlet.FileCleanerCleanup
</listener-class>
</listener>
來(lái)源:
http://fratemity1314.spaces.live.com/Blog/cns!E3BCC13A1E72BB4F!222.entryQ: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時(shí),表單里的屬性值不能用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)時(shí)報(bào)異常
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活動(dòng)超時(shí)限制的時(shí)間太短 HTTP Keep-Alive Timeout.
6,InputStream is =formFile.getInputStream() ;? //formFile是org.apache.struts.upload.FormFile
上傳的文件小時(shí)這個(gè)輸入流是java.io.ByteArrayInputStream,上傳比較大的文件時(shí)這個(gè)輸入流是FileInputStream
7,設(shè)置表單里的上傳路徑為只讀
<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