基於spring-boot的web應用,ckeditor上傳文件圖片文件


說來慚愧,這個應用調試,折騰了我一整天,google了很多帖子,才算整明白,今天在這里做個記錄和分享吧,也作為自己后續的參考!

 

第一步,ckeditor(本博文論及的ckeditor版本4.5.6)的配置圖片文件上傳功能,默認這個是沒有開啟的,就不用多說,ckeditor官網上也說的很清楚!http://docs.ckeditor.com

下面簡單的說下配置(配置文件algoConfig.js):

 1 CKEDITOR.editorConfig = function( config ) {
 2     config.toolbarGroups = [
 3         { name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
 4         { name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
 5         { name: 'editing', groups: [ 'find', 'selection', 'spellchecker', 'editing' ] },
 6         { name: 'forms', groups: [ 'forms' ] },
 7         '/',
 8         { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
 9         { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi', 'paragraph' ] },
10         { name: 'links', groups: [ 'links' ] },
11         { name: 'insert', groups: [ 'insert' ] },
12         '/',
13         { name: 'styles', groups: [ 'styles' ] },
14         { name: 'colors', groups: [ 'colors' ] },
15         { name: 'tools', groups: [ 'tools' ] },
16         { name: 'others', groups: [ 'others' ] },
17         { name: 'about', groups: [ 'about' ] }
18     ];
19 
20     config.removeButtons = 'Source,Save,NewPage,Scayt';
21     config.image_previewText=' ';     //預覽區域顯示內容
22     config.filebrowserImageBrowseUrl = '/browse/mgmt/img';
23     config.filebrowserImageUploadUrl = '/upload/mgmt/img'; 24 };

上圖中,背景顏色加高亮的為關鍵配置。等號左邊的是key,等號右邊的,則對應於web應用中的一個url,這個是配合后台應用中一個controller的處理,也就是一個servlet的操作。具體如何處理,后面再說!

 

再多羅嗦一下,我的這個配置中,涉及到圖片預覽區的那堆看不懂的文字的去除處理。我將其清掉了!如上面的21行的配置。另外,我的ckeditor工具欄中,去掉了一部分的button。具體如何操作,可以參考ckeditor的samples下面的toolbarconfigurator里面有個index.html,在瀏覽器里打開,可以參照着說明即可定制自己的工具欄

 

在應用的js文件中作如下的配置,即可以enable定制的CKeditor。

1 /**
2  * 下面是用CKeditor進行編輯文件
3  */        
4 CKEDITOR.replace( 'practice_content',    // practice_content是html文件中的對應的textarea編輯區的ID名稱,注意不要寫成#practice_content 5 {
6     language: 'zh-cn',
7     uiColor: '#c3c8d1',
8     customConfig: '/js/ckeditor/algoConfig.js' //自定義自己的toobar風格
9 });

 

到現在為止,定制的CKeditor的圖片上傳配置部分算是結束了。

此時,可以看到頁面上的ckeditor的狀態為下圖所示:

說明下: 圖中1標記對應配置:config.filebrowserImageUploadUrl = '/upload/mgmt/img';

     圖中2標記對應配置:config.filebrowserImageBrowseUrl = '/browse/mgmt/img';

          圖中3標記對應配置:config.image_previewText=' ';

 

第二步,就是圖片文件上傳的后台處理了,這步就是添加url /upload/mgmt/img的后台響應。由於ckeditor的文件上傳是采用的表單form以post的方式提交enctype為multipart/form-data的文件到后台服務器(此數據可以從html頁面debug方式查看,如下圖所示),那么對應的后台文件接受,則也采用Multipartfile的形式。

 

所以,后台的程序,應該也不是很難實現的事情。我就直接貼代碼了,有興趣的,自己可以看看!

 1 @RequestMapping(value="/upload/mgmt/img", method=RequestMethod.POST)
 2     public void handleFileUpload(User user,  @RequestParam("upload") MultipartFile file, 
 3             HttpServletRequest request, HttpServletResponse response){
 4         String name = "";
 5         if (!file.isEmpty()) {
 6             try {
 7                 response.setContentType("text/html; charset=UTF-8");  
 8                 response.setHeader("Cache-Control", "no-cache");  
 9                 response.setHeader("X-Frame-Options", "SAMEORIGIN"); 10                 PrintWriter out = response.getWriter();
11                 
12                 String fileClientName = getFileName(file.getOriginalFilename());  
13                 String fileFix = StringUtils.substring(fileClientName,  
14                         fileClientName.lastIndexOf(".") + 1);  
15                 if (!StringUtils.equalsIgnoreCase(fileFix, "jpg")  
16                         && !StringUtils.equalsIgnoreCase(fileFix, "jpeg")  
17                         && !StringUtils.equalsIgnoreCase(fileFix, "bmp")  
18                         && !StringUtils.equalsIgnoreCase(fileFix, "gif")  
19                         && !StringUtils.equalsIgnoreCase(fileFix, "png")) {  
20                     logger.error("Incorrect format of the uploading file -- " + fileFix);  
21                     return;  
22                 }  
23   
24                 if (logger.isInfoEnabled()) {  
25                     logger.info("Begin uploading: " + file.getName());  
26                 }  
27   
28                 // 為了客戶端已經設置好了圖片名稱在服務器繼續能夠明確識別,這里不改名稱 
29                 // 獲取目錄  
30                 File floder = buildFolder(user, request, FileType.IMAGE); 31                 if (null == floder) {  
32                     logger.info("folder is null");            
33                     return;  
34                 }  
35                 
36                 File newfile = new File(floder, fileClientName);
37                 byte[] bytes = file.getBytes();
38                 BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(newfile));
39                 stream.write(bytes);
40                 stream.close();
41   
42                 if (logger.isInfoEnabled()) {  
43                     logger.info("Uploading done,floder: " + newfile.getPath());  
44                 }  
45   
46                 // 組裝返回url,以便於ckeditor定位圖片
47 String fileUrl = request.getContextPath() + MueasConstants.APP_RUNNING_FILES_DIR; 48 fileUrl += IMAGE_DIR + File.separator + newfile.getName(); 49 fileUrl = StringUtils.replace(fileUrl, "//", "/"); 50       
51                 // 將上傳的圖片的url返回給ckeditor  
52                 String callback = request.getParameter("CKEditorFuncNum");  
53                 String script = "<script type=\"text/javascript\">window.parent.CKEDITOR.tools.callFunction(" + callback + ", '" + fileUrl + "');</script>";  
54                 
55                 out.println(script);
56                 out.flush();  
57                 out.close();  
58             } catch (Exception e) {
59                 logger.info("You failed to upload " + name + " => " + e.getMessage());
60             }
61         } else {
62             logger.info("You failed to upload " + name + " because the file was empty.");
63         }
64     }

其中,代碼里面的紅色部分比較值得注意,其他都不是太難的事情。

第一處紅色部分是為了解決下面的錯誤:

Refused to display 'http://localhost:8080/upload/mgmt/img?CKEditor=practice_content&CKEditorFuncNum=1&langCode=zh-cn' in a frame because it set 'X-Frame-Options' to 'DENY'.

第二處(30行)和第三處(47-49行)是為了讓上傳上來的文件存放的位置和ckeditor上傳文件獲取的URL地址(GET方式)的一致性。

這里再上傳一下創建存放文件的目錄的代碼:

 1 private File buildFolder(User user, HttpServletRequest request, FileType type) { 
 2   
 3         String realPath = request.getSession().getServletContext().getRealPath(MueasConstants.APP_RUNNING_FILES_DIR);
 4         String folderdir = "";
 5         //如果不存在,創建  
 6         switch(type){
 7         case IMAGE:
 8             folderdir += realPath + IMAGE_DIR;
 9             break;
10         case FILE:
11             folderdir += realPath + FILE_DIR;
12             break;
13         case FLASH:
14             folderdir += realPath + FLASH_DIR;
15             break;
16         case VIDEO:
17             folderdir += realPath + VIDEO_DIR;
18             break;
19         }  
20   
21         File floder = new File(folderdir);  
22         if (!floder.exists()) {  
23             if (!floder.mkdirs()) {  
24                 logger.error("Create folder failed! path=" + folderdir);  
25                 return null;  
26             }    
27         }  
28         return floder;        
29     }  

這里,根據文件類型,創建不同的子目錄。其中重點是request.getSession().getServletContext().getRealPath(MueasConstants.APP_RUNNING_FILES_DIR);這個,大家若不是很明白,可以查看一下文檔。

另外,就是配合使用的request.getContextPath() + MueasConstants.APP_RUNNING_FILES_DIR;總之,就是為了讓地址一致,存放文件的位置地址要讓取文件的GET指令能夠得到文件即可。

 

最后說下,為了控制上傳文件的大小,在spring-boot的配置文件中添加下面的信息:

multipart.maxFileSize = 3Mb
multipart.maxRequestSize = 20Mb

 

運行起來后,可以做測試圖片文件上傳的功能了,效果如下圖所示:

此時,點擊“確定”按鈕,圖片文件就會顯示在自己設計的textarea的區域了。是不是不那么難? 

 

話說回來,調通了是覺得不難,但是,在沒有調通的時候,就那個x-options-frame的問題,就讓我很頭疼。

其次,在后台處理的代碼中,起初,我采用的是commons-fileupload插件中的代碼處理的,但是總不成功,一下午,google了很多外文帖子,也不湊效,遂改成上面的代碼處理。其commons-fileupload關鍵參考代碼如下:

 1     DiskFileItemFactory factory = new DiskFileItemFactory();
 2     // maximum size that will be stored in memory
 3     factory.setSizeThreshold(maxMemSize);
 4 
 5     // Create a new file upload handler
 6     ServletFileUpload upload = new ServletFileUpload(factory);
 7     // maximum file size to be uploaded.
 8 
 9     upload.setSizeMax(maxFileSize);
10 
11     List<FileItem> fileItems = upload.parseRequest(request);

測試過程中,總是遇到列表filetems為空的問題,其實request中是有上傳過來的文件信息的。折騰了很久,還是沒有找到原因。算一個Open Point吧,若有高人或者過來人,可以給我指點一下。

 


免責聲明!

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



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