近兩天來由于項目需要使用上傳組件,于是我仔細分析了Cos和FileUpload的源代碼,并對它們的性能進行了測試比較,
使用2M、20M、45M、200M的上傳大小測試三種組件所花費的時間(單位為ms)結果是:
2M
|
第1次 |
第2次 |
第3次 |
第4次 |
平均 |
Cos |
297 |
203 |
234 |
245 |
245 |
FileUpload |
281 |
312 |
281 |
312 |
297 |
SmartUpload |
531 |
594 |
485 |
532 |
536 |
20M
|
第1次 |
第2次 |
第3次 |
第4次 |
平均 |
Cos |
2562 |
2109 |
2719 |
2172 |
2391 |
FileUpload |
4062 |
4140 |
5360 |
3922 |
4371 |
SmartUpload |
3453 |
3094 |
3078 |
3547 |
3293 |
45M
|
第1次 |
第2次 |
第3次 |
第4次 |
平均 |
Cos |
4860 |
4844 |
5125 |
5171 |
5000 |
FileUpload |
9000 |
8391 |
10375 |
10078 |
9461 |
SmartUpload |
8265 |
9187 |
8672 |
8856 |
8745 |
200M
|
第1次 |
第2次 |
第3次 |
第4次 |
平均 |
Cos |
55813 |
52282 |
54796 |
51187 |
53520 |
FileUpload |
76343 |
68531 |
80954 |
79031 |
76215 |
SmartUpload |
內存堆棧溢出 |
|
|
|
|
從上述的表格對比中可以看出Cos始終保持著良好的性能。在上傳量較?。ㄈ萘?/SPAN><2M,這是最常出現的情況)時,Cos比FileUpload性能并沒有好很多,但SmartUpload就已經開始顯出弱勢。
隨著容量的增大,FileUpload和SmartUpload的性能下降非??欤钡?/SPAN>200M容量時,SmartUpload已經不堪重負崩潰了,而Cos此時的花費時間比FileUpload少了20多秒,不能不說在本次的評測中,Cos的性能位居第一。
通過對三種流行的上傳組件進行對比,我認為選用Cos是比較好的。在實際的項目中,可以把上傳的文件放到文件夾,文件路徑存于數據庫中以便于管理。
如果需要把文件上傳到數據庫也很簡單,從Cos中已經得到了上傳文件(java.io.File),其后的操作很平常所做的一樣: 通過File得到inputStream,存到數據庫的blob或Clob字段即可。
對于使用Struts的項目,我覺得還是使用FileUpload比較好,因為Struts天生集成了FileUpload的功能,使用FileUpload會帶來很多的便利。而如果想要開發獨立的上傳組件,則用Cos是最好的選擇,可以在Cos的基礎上封裝一層,暴露給業務程序員的只是一些簡單易用的API,而且可以給這些API加上自定義的javaDoc,這對于實際的開發和將來的擴展都是非常方便的。
下面對FileUpload的上傳機制作一些分析,基本上,上傳一個文件的過程在FileUpload中可以分為三個部分:
1.由客戶端把要上傳的文件生成request數據流,與服務器端建立連接
2.在服務器端接收request流,將流緩存到內存或磁盤中(具體緩存到什么地方,將由DiskFileUpload的setSizeThreshold(int cacheMax)方法來決定,當文件大小<cacheMax時,文件將被緩存到內存,否則將被緩存到磁盤的臨時文件)
3.由服務器端的內存或是臨時文件中把文件輸出到指定的目錄(這個目錄才是指定的文件上傳目錄).
上述的第一步由瀏覽器完成,不用過多理會,重點是第二和第三步。
第二步時,由DiskFileUpload的parseRequest(...)方法(其實這個方法是繼承于FileUploadBase類,真正起解析request流作用的類是FileUploadBase)解析request流。在parseRequest(...)方法中,新建了一個MultipartStream實例,由此實例的readBodyData()方法將上傳文件的流讀到FileItem實例中,FileItem實例根據設置好的cacheMax大小,引用一個內存中的數據流或是一個磁盤上的數據流,注意此時文件已經上傳到了服務器,但仍然沒有傳到設定的上傳目錄。
第三步時,調用FileItem實例的write(File file)方法,將已經存在于內存或是磁盤上的上傳文件流拷貝到設定好的上傳目錄,至此上傳仍未結束,因為磁盤中很可能保存了上傳文件的臨時文件(當設定的cacheMax<文件大小時),如何刪除這些臨時文件?有兩種方法:1.顯示調用FileItem實例的delete()方法。2.不調用任何方法,當FileItem被垃圾回收時,由finalize()方法刪除臨時文件。