Java文件上傳組件,Fastupload 0.31 功能完備速度飆升

openkk 12年前發布 | 25K 次閱讀 Fastupload

fastupload 0.31版本上周已經發布,因為工作的關系,只到今天才有點時間來寫一些0.31版本中深層次的東西。fastupload以前的版本,盡管在性能上取得 了不小的進步,但只支持解析文件,不支持解析非文件的內容,因為HttpFileUploadParser這個類來解析ServletRequest的輸 入流的過程中,忽略非文件的請求數據。舉個列子來說,假如表單中有兩個input標簽,一個是文本輸入控件,一個是文件輸入控件,經過 HttpFileUploadParser解析后,只會把文件類型請求的數據保存在指定的目錄下。

在fastupload項目編寫之初,考慮的是如何把文件類型請求的數據保存到文件中去,在這種目標下,如何處理非文件類型請求數據?自然的”選擇“了忽略這種方式。

在fastupload 0.23發布后 ,原計劃是在下一個版本中提供對struts2、spring mvc3的注解(annotation)一些高級特性的支持,有些網友對fastupload提出了批評和建議,其中,網友silence1214 提出了對于非文件類型請求數據的處理問題。經過仔細考慮后,決定先實現非文件類型請求數據的處理。于是,0.31版本中,類HttpMemoryUploadParser能處理非文件類型的請求數據了,具體的示例代碼如下,

MultiPartDataFactory mpdf = new MemoryMultiPartDataFactory("utf-8");
        HttpMemoryUploadParser uploadParser = new HttpMemoryUploadParser(request, mpdf);
        long s = System.currentTimeMillis();
        List<MultiPartData> list = uploadParser.parseList();

        File dir = new File(System.getProperty("user.home") + "/memoryupload/dump");
        dir.mkdirs();

        for (MultiPartData e : list) {
            String target = String.format("%s/%s", dir.getAbsolutePath(), e.getFileName());
            if (e.isFile()) {
            e.toFile(target);
            }
            else {
                System.out.println(new String(e.getContentBuffer()));
            }
        }

        System.out.format("memoryupload cost: %d %n", System.currentTimeMillis() - s);

 

當新建一個HttpMemoryUploadParser類的實例時,首先讀取ServletRequest輸入流中所有的字節,寫入內存緩沖中,parseList()函數從這片大的緩沖中解析上傳表單中的內容,返回一個包含MultiPartData類型的數組。

 

這里的MultiPartData是multipart/form-data中兩個邊界(boundary)中數據的一個抽象。上傳請求數據中的頭 部信息表明這部分數據是一個文件中的內容,還是輸入控件中“輸入”的內容,MultiPartData.isFile()函數則實現了這個判斷功能,此 外,MultiPartData.getContentHeaderMap()函數把這些“頭部信息”以Map的形式暴露出來,供外部代碼使用。

在成功解析上傳表單后,每個MultiPartData都有一個自己的一片內存緩沖,用于保存解析后所得出的數據,如果需要把這些數據保存到文件中 去,則調用toFile()函數,如果想直接獲得數據,則調用getContentBuffer()函數。需要提醒的是,創建 MemoryMultiPartDataFactory時,指定了字符集,MemoryMultiPartDataFactory在創建 MemoryMultiPartData對象時,對把name屬性轉換成所指定的字符集字符串,對于所解析出的內容,并不做字符集的轉換,因為數據已經讀 入到內存中,開發人員可以對其轉換成所期望的字符集,不象MultiPartTextFile寫入時,需要強制進行字符集轉換。

對于支持非文件類型請求后,fastupload和Apache Commons FileUpload的性能相比,是一個什么樣的結果呢?繼續做一個實際的測試對比,分別用fastupload的 HttpMemoryUploadParser和Apache Commons FileUpload的相類似的API接受1.7M、1.7M和1.2M的圖像文件。得到下面的測試結果,單位毫秒。

memoryupload cost: 10 
memoryupload cost: 8 
memoryupload cost: 11 
memoryupload cost: 8 
memoryupload cost: 12 
memoryupload cost: 8 
memoryupload cost: 48 
memoryupload cost: 14 
memoryupload cost: 346 
memoryupload cost: 11 
memoryupload cost: 8 
memoryupload cost: 9 
memoryupload cost: 14 
memoryupload cost: 8 
memoryupload cost: 14 
memoryupload cost: 9 
memoryupload cost: 10 
memoryupload cost: 14 
memoryupload cost: 10 
memoryupload cost: 12 
Apache Common File Upload costs: 379 
Apache Common File Upload costs: 29 
Apache Common File Upload costs: 66 
Apache Common File Upload costs: 87 
Apache Common File Upload costs: 92 
Apache Common File Upload costs: 24 
Apache Common File Upload costs: 195 
Apache Common File Upload costs: 286 
Apache Common File Upload costs: 25 
Apache Common File Upload costs: 314 
Apache Common File Upload costs: 50 
Apache Common File Upload costs: 84 
Apache Common File Upload costs: 217 
Apache Common File Upload costs: 86 
Apache Common File Upload costs: 314 
Apache Common File Upload costs: 120 

可以看出,兩組數據中,最快的單次時間比是8:24,如果比較兩組數據中前10個的平均值,這個比是8.8:51,如果比較最慢的10個數據的平均值,是49.6:229, 最慢的單次比值是 346:379,相差不大,平均時間比是29.2:140。

總的說來,得益于改進的BM查找算法,HttpMemoryUploadParser解析速度比Apache Commons FileUpload的要快好很多,速度上占據了絕對的優勢,從最慢那個對比來看,fastupload仍然有提高的空間,比如說盡可能的優化內存的使 用。

開源fastupload項目純粹我當時的一個想法,沒想到引起了廣大網友的注意,不屑、質疑、建議、批評的都有,不管怎么說,你們的聲音是fastupload項目前進中動力的重要部分,這里特別感謝廣大網友。

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