|
我對表單上傳的理解(可能有誤): ?<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.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時,表單里的屬性值不能用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
1,hipergate ?又是西班牙出的,為什么西班牙和葡萄牙兩牙都喜歡ERP開源呢? 口氣很大,看他說的:什么使hipergate如此獨一無二?
It is completely free.
It is the only Open Source application with such a wide functional coverage.
Runs on multiple databases and operating systems
Has a unitary conceptual design and implementation.
Is adequate for being used by Application Service Providers.
Supports multiple languages.
Has a professional services support network.
Is well documented.
hipergate所有的實體類都繼承自com.knowgate.dataobjs.DBPersist,好像增刪改查的代碼都不用自己寫了,值得研究。 2,vtiger 就更狂妄了,竟然聲稱是"The best OpenSource CRM on the planet"! ?? 看過其demo,做得還真不賴,模塊比較齊全,界面上很多細節處理得很精致,比較人性化,可惜不是java做的。為什么很多java做的web系統聽起來牛鼻子哄哄的,使用起來卻慘不忍睹?真想把vtiger的老虎皮剝下來用在我的java上。 3,oaj ,貌似不錯,可惜已經兩年多沒更新了。 ??? OAJ (OpenAccountingJ) is a free, open-source, web-based Accounting/ERP system. Built in Java using the best-of-breed Open Source components, such as Spring Framework, Acegi Security, Hibernate, Jasper Reports, XDoclet it offers a solid, customizable, secure platform for your business.
4,Openbravo 和Compiere這兩個就不說了。
5,ADempiere
6,cream
用turbine開發的,持久用的torque。大概看了下,確實有他的一套。 7,icehrm 用了extgwt,不感興趣。不過好像也用了torque
8,預算軟件 Adaptive Planning Express 可惜太大了,而且好像用的swing http://sourceforge.net/projects/adaptiveplan/files/
1,云網OA 用戶名zhao,密碼123 http://218.206.128.201:8888/oademo/?
2,極品OA http://www.ijipin.com/VOA/login.jsp源碼|打包|軟件|黑防|模板|調試|教材|網站:[-w'?+w4l*L#F;`*Q
測試用戶:test1到test5 bbs.jzpu.com2k,w/k!u&?'L5f*e0u 密碼全部為空 3,http://www.tinzoom.com/phr01.htm#b03 4,orangehrm php開源hr http://sourceforge.net/projects/orangehrm
select fk_col.constraint_name, fk_col.table_name, fk_col.column_name ? from user_constraints pk, user_constraints fk, user_cons_columns fk_col ?where pk.table_name = 'TEST' ?? and pk.constraint_type = 'P' ?? and fk.r_constraint_name = pk.constraint_name ?? and fk_col.constraint_name = fk.constraint_name ?order by 2, 3;
select?a.table_name?外鍵表名,a.column_name?外鍵列名,b.table_name?主鍵表名,b.column_name?主鍵列名 from?
(select?a.constraint_name,b.table_name,b.column_name,a.r_constraint_name from?user_constraints?a,?user_cons_columns?b WHERE?a.constraint_type='R' and?a.constraint_name=b.constraint_name
)?a,
(select?distinct?a.r_constraint_name,b.table_name,b.column_name from?user_constraints?a,?user_cons_columns?b WHERE???a.constraint_type='R' and?
a.r_constraint_name=b.constraint_name)
b where?a.r_constraint_name=b.r_constraint_name
? extremetable導出excel,彈出一個下載窗口,這時不點下載而點取消,則報下面的異常: ClientAbortException? Caused by: java.net.SocketException: Connection reset by peer: socket write error
查了下TOMCAT的文檔,解釋如下: Wrap an IOException identifying it as being caused by an abort of a request by a remote client. 在BAIDU和GOOGLE上找了下原因,大概歸結為: ClientAbortException: java.net.SocketException: Connection reset by peer: socket write error的原因是由于處理http連接時,正在輸出內容時,用戶關閉了IE,會出現一個"ClientAbortException",屬于I/O處理中出現的一個異常,應用服務器應該會捕捉。 Connection reset by peer的原因: 經常出現的Connection reset by peer: 原因可能是多方面的,不過更常見的原因是: ①:服務器的并發連接數超過了其承載量,服務器會將其中一些連接Down掉; ②:客戶關掉了瀏覽器,而服務器還在給客戶端發送數據; ③:瀏覽器端按了Stop 很多人都說是客戶端造成的,沒有辦法控制,是個比較郁悶的問題。
但是,我擔心的是:雖然前臺沒有任何出錯的跡象,但是后臺會記錄這個異常,日志也會瘋狂爆滿,時間長了,肯定會DOWN掉的,還沒找到好的解決辦法 resin有一個參數ignore-client-disconnect tomcat似乎沒有
經常出現的Connection reset by peer:
原因可能是多方面的,不過更常見的原因是:①:服務器的并發連接數超過了其承載量,服務器會將其中一些連接Down掉;②:客戶關掉了瀏覽器,而服務器還
在給客戶端發送數據;③:瀏覽器端按了Stop
[10054] Connection reset by peer Connection reset by peer is a
tough one because it can be caused by so many things. In all cases, the
server determines that the socket is no longer good and closes it from
its side. Read Error Scenario: Mary couldn't make out what Joe
was saying anymore, so she hung up rather than lose his messages
(data). A read error occurs when a server cannot successfully read
from a user's client. Servers gather information from the client by
text, setup, and other items.When the server receives an error when
reading from a client, it then disconnects the user, resulting in a read
error quit message. Write Error Scenario: Mary was trying to
talk to Joe but didn't think she was getting through, so she hung
rather than lose his messages (data). A write error occurs when a
server cannot successfully write to a user's client. When the server
receives information, it usually responds with information of its own.
When the server receives an error when writing to a client, it then
disconnects the user, resulting in a write error quit message similar to
the read error format. Ping Timeout Error Scenario: Mary,
having been raised in a household with too many kids and always craving
attention, keeps asking to make sure that Joe is still on the line and
listening. If he doesn't reply fast enough to suit her, she hangs up.
Servers automatically ping users at a preset time. The reason for this
is to ensure the client is still connected to the server. When you see
"PING? PONG!" results in your status window, it means the server has
pinged your client, and it has responded back with a pong to ensure the
server that you are still connected. When this does not happen and you
disconnect without the server's knowledge, the server will automatically
disconnect the user when it does not receive a response, resulting in a
ping timeout. Ping timeouts occur to EVERYONE. Broken pipe Error
Scenario: Mary had picked up a sticky note with a message she needed to
relay to Joe, but somehow between her hand and her mouth, the message
got misplaced. Mary was trying to talk to Joe but didn't think she was
getting through, so she hung up rather than lose his messages (data).
A broken pipe error occurs when the server knows it has a message but
can't seem to use its internal data link to get the data out to the
socket. Miscellaneous Scenario: Lots of other reasons;
perhaps the operator broke in and gave Mary a message that made her
doubt the validity of the call so she hung up
最近寫代碼時發現用BufferedReader把InputStream包裝后,使用BufferedReader讀取后,然后再使用 InputStream讀取時總是發現問題,好像總是丟數據,由于我在流里面同時混了二進制數據與字符串,所以很不好調度,然后專門寫了下面的代碼去測試發現原來是. BufferedReader讀取數據時會把數據從流里面取出一部分緩存,如果你再轉向去用InputStream去讀取的話,BufferedReader緩存里面的數據InputStream是讀取不到的 . package bytearray; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; public class TestByteArray { public byte[] generateByte() { // 構造一個測試流,這樣就不用從文件里面讀取了,在這個流里面使用了大量的回車換行("\r\n"),這樣方便過會的測試 // 過會,我會通過把字符串轉換成byte數組,然后通過ByteArrayInputStream來構造一個數據流 return "a\r\nbc\r\ndef\r\nghi\r\nj\r\nklmn\r\nopqr\r\ns\r\ntuvwxyz " .getBytes(); } public static void main(String[] args) throws IOException { // TODO Auto-generated method stub TestByteArray self = new TestByteArray(); byte[] be = self.generateByte(); InputStream in = new ByteArrayInputStream(be); BufferedReader bufferReader = new BufferedReader(new InputStreamReader( in)); // 使用DataInputStream而不直接使用Inputstream是因為這樣方便,因為他提供了讀取行 // 不過聽說他讀取行時把字節轉變為字符時會有問題,所以不推薦使用,不過我們在這只做測試就沒關系了 DataInputStream dataInputStream = new DataInputStream(in); // 先讀取流里面的一行數據 System.out.println("bufferReader=" + bufferReader.readLine()); // 回過頭來使用dataInputStream讀取數據,會發現什么也讀取不到 System.out.println("dataInputStream=" + dataInputStream.readLine()); // 回過頭來使用inputstream讀取數據,會發現什么也讀取不到 System.out.println("in=" + in.read()); // InputStream讀取不到數據,然后再使用原來的BufferedReader來讀取數據,發現是接著原來讀取的. System.out.println("bufferReader=" + bufferReader.readLine()); //我們上面的字符串比較小,我想如果字符串,大到緩存裝不下的時候,使用inputstream回頭去讀取數據,肯定是能讀取到的 //這個我就不測試了 } } 轉自 http://itspy.spaces.live.com/blog/cns!87AF3B24336DF461!180.entry
|