SpringMVC+SwfUpload進行多文件同時上傳


由於最近項目需要做一個多文件同時上傳的功能,所以好好的看了一下各種上傳工具,感覺uploadify和SwfUpload的功能都比較強大,並且使用起來也很方便。SWFUpload是一個flash和js相結合而成的文件上傳插件,而且該插件可以用在php、.net、Java等項目開發中。在使用的過程中需要引入兩個js文件,並且進行相關參數的配置,同時也可以定義一系列的事件,如:上傳成功事件,上傳失敗事件,正在上傳事件等等。由於我在項目開發是使用SpringMVC進行的,所以下面我根據我自己的項目簡述一下SwfUpload如何整合到Web項目中去。

首先說一下Swfupload相對於HTML中file標簽上傳的優點:

  • 允許一次上傳多個文件,但會有一個上傳隊列,隊列里文件的上傳是逐個進行的,服務器端接收文件時跟普通的表單上傳文件是一樣的(相當於表單一次提交了一個file,但是提交了多次,后台處理的時候只需要處理一次即可);
  • 用flash進行上傳,頁面無刷新,且可自定義Flash按鈕的樣式, 類似AJAX的無刷新上傳,里面可以引入swf文件實現動態效果;
  • 可以顯示上傳進度,也可以在瀏覽器端就對要上傳的文件格式,大小等進行配置(只需要配置一個參數即可,比用js的數據驗證要好很多);
  • 良好的瀏覽器兼容性並且兼容其他JavaScript庫 (例如:jQuery,EXT, Prototype等);一般含有flash插件的即可正常運行,但是好像最低要求flash的版本要達到flash9;
  •  SwfUpload還提供了豐富的事件接口供開發者使用;開發者可以自定義各種和上傳相關的事件;

SWfUpload實現文件的上傳流程如下:

1、引入相應的js文件 (swfupload.js和swfupload.queue.js必須引入)
2、實例化SWFUpload對象,傳入一個配置參數對象進行各方面的配置。 
3、點擊SWFUpload提供的Flash按鈕(也可以更改配置信息中的button_image_url參數來配置自己的按鈕),彈出文件選取窗口選擇要上傳的文件; 
4、文件選取完成后符合規定的文件會被添加到上傳的隊列里; 
5、調用startUpload方法讓隊列里文件開始上傳; 
6、文件上傳過程中會觸發相應的事件(想要觸發什么事件需要自己定義,但是一般網上搜一下就可以了,大部分定義都相同,我也會貼出我的代碼),開發者利用這些事件來更新ui、處理錯誤、發出提示等等; 

下面說我的項目中SpringMVC+SwfUpload的配置過程及代碼:

引入相應的JS文件后實例化SwfUpload對象(JS代碼,一般嵌入到jsp文件中或者單獨寫一個文件引入到jsp頁面內):

 1     var swfu;
 2 
 3         window.onload = function() {
 4             var settings = {
 5                 flash_url : "swfupload/swfupload.swf",
 6                 flash9_url : "swfupload/swfupload_fp9.swf",
 7                 upload_url: "http://localhost:8080/ams/upload/fileUpload.do",
 8                 post_params: {"PHPSESSID" : "aa"},
 9                 file_size_limit : "100 MB",
10                 file_types : "*.*",
11                 file_post_name : "filedata",
12                 file_types_description : "All Files",
13                 file_upload_limit : 100,
14                 file_queue_limit : 0,
15                 custom_settings : {
16                     progressTarget : "fsUploadProgress",
17                     cancelButtonId : "btnCancel"
18                 },
19                 debug: true,
20 
21                 // Button settings
22                 button_image_url: "images/TestImageNoText_65x29.png",
23                 button_width: "65",
24                 button_height: "29",
25                 button_placeholder_id: "spanButtonPlaceHolder",
26                 button_text: '<span class="theFont">Hello</span>',
27                 button_text_style: ".theFont { font-size: 16; }",
28                 button_text_left_padding: 12,
29                 button_text_top_padding: 3,
30                 
31                 // The event handler functions are defined in handlers.js
32                 swfupload_preload_handler : preLoad,
33                 swfupload_load_failed_handler : loadFailed,
34                 file_queued_handler : fileQueued,
35                 file_queue_error_handler : fileQueueError,
36                 upload_start_handler : uploadStart,
37                 upload_progress_handler : uploadProgress,
38                 upload_error_handler : uploadError,
39                 upload_success_handler : uploadSuccess
40             };
41 
42             swfu = new SWFUpload(settings);
43          };                
View Code

編寫相關的監聽事件(JS代碼,即html引入的handler.js文件):

  1 function preLoad() {
  2     if (!this.support.loading) {
  3         alert("You need the Flash Player 9.028 or above to use SWFUpload.");
  4         return false;
  5     }
  6 }
  7 function loadFailed() {
  8     alert("Something went wrong while loading SWFUpload. If this were a real application we'd clean up and then give you an alternative");
  9 }
 10 
 11 function fileQueued(file) {
 12     try {
 13         var progress = new FileProgress(file, this.customSettings.progressTarget);
 14         progress.setStatus("Pending...");
 15         progress.toggleCancel(true, this);
 16 
 17     } catch (ex) {
 18         this.debug(ex);
 19     }
 20 
 21 }
 22 
 23 function fileQueueError(file, errorCode, message) {
 24     try {
 25         if (errorCode === SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED) {
 26             alert("You have attempted to queue too many files.\n" + (message === 0 ? "You have reached the upload limit." : "You may select " + (message > 1 ? "up to " + message + " files." : "one file.")));
 27             return;
 28         }
 29 
 30         var progress = new FileProgress(file, this.customSettings.progressTarget);
 31         progress.setError();
 32         progress.toggleCancel(false);
 33 
 34         switch (errorCode) {
 35         case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
 36             progress.setStatus("File is too big.");
 37             this.debug("Error Code: File too big, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
 38             break;
 39         case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
 40             progress.setStatus("Cannot upload Zero Byte files.");
 41             this.debug("Error Code: Zero byte file, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
 42             break;
 43         case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
 44             progress.setStatus("Invalid File Type.");
 45             this.debug("Error Code: Invalid File Type, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
 46             break;
 47         default:
 48             if (file !== null) {
 49                 progress.setStatus("Unhandled Error");
 50             }
 51             this.debug("Error Code: " + errorCode + ", File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
 52             break;
 53         }
 54     } catch (ex) {
 55         this.debug(ex);
 56     }
 57 }
 58 
 59 function fileDialogComplete(numFilesSelected, numFilesQueued) {
 60     try {
 61         if (numFilesSelected > 0) {
 62             document.getElementById(this.customSettings.cancelButtonId).disabled = false;
 63         }
 64         
 65         /* I want auto start the upload and I can do that here */
 66         this.startUpload();
 67     } catch (ex)  {
 68         this.debug(ex);
 69     }
 70 }
 71 
 72 function uploadStart(file) {
 73     try {
 74         /* I don't want to do any file validation or anything,  I'll just update the UI and
 75         return true to indicate that the upload should start.
 76         It's important to update the UI here because in Linux no uploadProgress events are called. The best
 77         we can do is say we are uploading.
 78          */
 79         var progress = new FileProgress(file, this.customSettings.progressTarget);
 80         progress.setStatus("Uploading...");
 81         progress.toggleCancel(true, this);
 82     }
 83     catch (ex) {}
 84     
 85     return true;
 86 }
 87 
 88 function uploadProgress(file, bytesLoaded, bytesTotal) {
 89     try {
 90         var percent = Math.ceil((bytesLoaded / bytesTotal) * 100);
 91 
 92         var progress = new FileProgress(file, this.customSettings.progressTarget);
 93         progress.setProgress(percent);
 94         progress.setStatus("Uploading...");
 95     } catch (ex) {
 96         this.debug(ex);
 97     }
 98 }
 99 
100 function uploadSuccess(file, serverData) {
101     try {
102         var progress = new FileProgress(file, this.customSettings.progressTarget);
103         progress.setComplete();
104         progress.setStatus("Complete.");
105         progress.toggleCancel(false);
106 
107     } catch (ex) {
108         this.debug(ex);
109     }
110 }
111 
112 function uploadError(file, errorCode, message) {
113     try {
114         var progress = new FileProgress(file, this.customSettings.progressTarget);
115         progress.setError();
116         progress.toggleCancel(false);
117 
118         switch (errorCode) {
119         case SWFUpload.UPLOAD_ERROR.HTTP_ERROR:
120             progress.setStatus("Upload Error: " + message);
121             this.debug("Error Code: HTTP Error, File name: " + file.name + ", Message: " + message);
122             break;
123         case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED:
124             progress.setStatus("Upload Failed.");
125             this.debug("Error Code: Upload Failed, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
126             break;
127         case SWFUpload.UPLOAD_ERROR.IO_ERROR:
128             progress.setStatus("Server (IO) Error");
129             this.debug("Error Code: IO Error, File name: " + file.name + ", Message: " + message);
130             break;
131         case SWFUpload.UPLOAD_ERROR.SECURITY_ERROR:
132             progress.setStatus("Security Error");
133             this.debug("Error Code: Security Error, File name: " + file.name + ", Message: " + message);
134             break;
135         case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
136             progress.setStatus("Upload limit exceeded.");
137             this.debug("Error Code: Upload Limit Exceeded, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
138             break;
139         case SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED:
140             progress.setStatus("Failed Validation.  Upload skipped.");
141             this.debug("Error Code: File Validation Failed, File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
142             break;
143         case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
144             // If there aren't any files left (they were all cancelled) disable the cancel button
145             if (this.getStats().files_queued === 0) {
146                 document.getElementById(this.customSettings.cancelButtonId).disabled = true;
147             }
148             progress.setStatus("Cancelled");
149             progress.setCancelled();
150             break;
151         case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
152             progress.setStatus("Stopped");
153             break;
154         default:
155             progress.setStatus("Unhandled Error: " + errorCode);
156             this.debug("Error Code: " + errorCode + ", File name: " + file.name + ", File size: " + file.size + ", Message: " + message);
157             break;
158         }
159     } catch (ex) {
160         this.debug(ex);
161     }
162 }
163 
164 function uploadComplete(file) {
165     if (this.getStats().files_queued === 0) {
166         document.getElementById(this.customSettings.cancelButtonId).disabled = true;
167     }
168 }
169 
170 // This event comes from the Queue Plugin
171 function queueComplete(numFilesUploaded) {
172     var status = document.getElementById("divStatus");
173     status.innerHTML = numFilesUploaded + " file" + (numFilesUploaded === 1 ? "" : "s") + " uploaded.";
174 }
View Code

編寫HTML頁面:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <title>SWFUpload Demos - Simple Demo</title>
 5 <link href="css/default.css" rel="stylesheet" type="text/css" />
 6 <script type="text/javascript" src="swfupload/swfupload.js"></script>
 7 <script type="text/javascript" src="swfupload/swfupload.queue.js"></script>
 8 <script type="text/javascript" src="js/fileprogress.js"></script>
 9 <script type="text/javascript" src="js/handlers.js"></script>
10 
11 <body>
12 <div id="header">
13     <h1 id="logo"><a href="../">SWFUpload</a></h1>
14     <div id="version">v2.5.0</div>
15 </div>
16 
17 <div id="content">
18     <h2>External Interface Demo</h2>
19     <form id="form1" action="index.php" method="post" enctype="multipart/form-data">
20         <p> This page tests rebuilding the External Interface after some kind of display change.  This demo isn't meant for building upon. Rather it
21         helps test whether a particular browser is suffering from this bug.</p>
22 
23         <div class="fieldset flash" id="fsUploadProgress">
24             <span class="legend">Upload Queue</span>
25         </div>
26         <div id="divStatus">0 Files Uploaded</div>
27         <div id="divMovieContainer">
28             <span id="spanButtonPlaceHolder"></span>
29             <input type="button" value="Start Upload" onclick="swfu.startUpload();" style="margin-left: 2px; font-size: 8pt; height: 29px;" />
30         </div>
31     
32 
33     </form>
34 </div>
35 </body>
36 </html>
View Code

后台處里代碼:

首先要配置SpringMVC配置文件,在配置文件中加入下面內容

1     <bean id="multipartResolver"  
2         class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
3         <!-- one of the properties available; the maximum file size in bytes -->  
4         <property name="maxUploadSize" value="10485760000000" />  
5     </bean>  
View Code

服務器接收程序:

 1 @ResponseBody
 2     @RequestMapping("/fileUpload.do")
 3     public String fileUpload(HttpServletRequest request,@RequestParam("filedata")MultipartFile file) throws Exception {
 4         
 5         request.setCharacterEncoding("utf-8");//解決亂碼問題 
 6         try{     
 7             String uploadDir = request.getServletContext().getRealPath("/upload");//獲取上傳目錄的路徑
 8             //獲得目錄,如果目錄不存在,則創建目錄
 9             File dirPath = new File(uploadDir);      
10             if (!dirPath.exists()) {      
11                 dirPath.mkdirs();      
12             }      
13             //開始文件上傳
14             InputStream inputStream = file.getInputStream(); //獲得輸入流     
15             String fileName = file.getOriginalFilename(); //獲得原始名字  
16 
17             String fileNameFull = uploadDir + "/" + fileName;   
18             OutputStream outputStream = new FileOutputStream(fileNameFull);//獲得輸出流     
19             int bytesRead = 0;      
20             byte[] buffer = new byte[8192]; 
21             
22             while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) 
23             {      
24                 //輸出到目標文件夾
25                 outputStream.write(buffer, 0, bytesRead);      
26             }      
27             outputStream.close();      
28             // close the stream      
29             inputStream.close(); 
30          }catch(Exception e){      
31              e.printStackTrace(); 
32              return "error";
33          }
34         return "ok";
35     }    
View Code

這樣經過上面的配置即可完成多文件同時上傳的例子了,注意的地方有幾點:

一是中文名亂碼問題,解決辦法:

1.在Java程序內加入一行代碼:request.setCharacterEncoding("utf-8");

2.進行編碼轉換,fileName = new String(fileName.getBytes("GBK"),"UTF-8");//反正就是進行編碼的轉換

3.好像還有其它的方法,但是我也不太懂了

還有一點是后台獲得file的時候名字問題:

后台獲得file是一個一個獲取的,即如果你上傳10個文件,那就是分十次來調用后台Java代碼的,每次調用上傳一個文件,所以后台只需要對一個文件進行處理即可,這些文件傳遞到后台的name屬性值是相同的,通過 file_post_name : "filedata"來進行配置,這個時候后台獲取file只要通過filedata即可了!

這是我初步了解了SwfUpload之后進行記錄的內容,希望以后自己能回來翻看學習。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM