1. 程式人生 > >wangEditor富文字編輯器

wangEditor富文字編輯器

 富文字編輯器,Rich Text Editor, 簡稱 RTE, 是一種可內嵌於瀏覽器,所見即所得的文字編輯器. 
CSDN的markdown編輯器便是一種富文字編輯器.

  藍莓商城商品詳情這一部分的編輯需要使用富文字編輯器.本來想使用百度的ueditor的,但是弄了好久依然還是有問題.所以就放棄了.ueditor配置確實比較複雜,官方的文件也沒有很好的說清楚,錯誤提示不夠明瞭,出錯時未提示具體的原因.

  最後找到這個wangEditor.相比ueditor,配置更加簡單,使用更加方便.其功能雖不及ueditor多,但是應付一般的需求足夠了. 
 

流程說明

 由於對於圖片上傳整個流程比較複雜,所以本文僅對其進行說明. 
 圖片上傳的流程是,當頁面選擇圖片後,將會建立XMLHttpRequest請求,將圖片資料傳送給服務端,服務端接收後將圖片儲存到本地,再將圖片路徑返回給客戶端,客戶端接收到圖片路徑後,建立元素,並將圖片路徑賦給src,最後再把該元素插入到編輯器中. 
 
 // 定義 xhr 傳送請求給服務端
  var xhr = new XMLHttpRequest();
   xhr.open('POST', uploadImgServer);

客戶端配置說明
下載
直接下載:https://github.com/wangfupeng1988/wangEditor/releases 
使用npm下載:npm install wangeditor (注意 wangeditor 全部是小寫字母) 
使用bower下載:bower install wangEditor (前提保證電腦已安裝了bower) 
使用CDN://unpkg.com/wangeditor/release/wangEditor.min.js

除錯階段推薦使用方式1中的未壓縮版本,因為如果出現問題也好除錯和查詢. 
下載後將目錄裡的wangEditor.js放入工程目錄中.只需要這個檔案,其他的不需要. 
 
我放在webapp下的wangEditor路徑下. 


前端配置
引入js檔案 
contextPathOfStatic這裡是我的專案路徑下的static資料夾:http://localhost:8080/lanmei-os/static

<script type="text/javascript" src="${contextPathOfStatic}/wangEditor/wangEditor.js"></script>
1
jsp頁面新增

<div id="editor">
 <!-- 預設顯示 -->
   <p>歡迎使用 <b>wangEditor</b> 富文字編輯器</p>
</div>

這裡我建立3個按鈕進行測試

<button id="editorSetBtn">設定內容</button>
<button id="editorGetBtn1">獲取內容1</button>
<button id="editorGetBtn2">獲取內容2</button>
js檔案編寫
$(function(){

    var E = window.wangEditor;
    //這裡的id為<div id="editor"中的id.
    var editor = new E('#editor');
    // 配置伺服器端地址,也就是controller的請求路徑,不帶專案路徑,前面沒有/
    editor.customConfig.uploadImgServer = 'commodity/upload/editor/img';
    //配置屬性名稱,繫結請求的圖片資料
    //controller會用到,可以隨便設定,但是一定要與controller一致
    editor.customConfig.uploadFileName = 'img';
    //建立編輯器
    editor.create();

    $("#editorSetBtn").click(function(){
        //這是設定編輯器內容
        editor.txt.html("dsafdfadsfdafdsfds");
    })
     $("#editorGetBtn1").click(function(){
      //獲取編輯器的內容,帶樣式
      //一般使用這個獲取資料,通過ajax傳送給服務端 ,然後服務端以String接收,儲存到資料庫.
         alert(editor.txt.html());
    })
     $("#editorGetBtn2").click(function(){
        //獲取編輯器的內容,不帶樣式,純文字
         alert(editor.txt.text());
    })
})

程式載入完之後頁面就會出現編輯器. 


客戶端設定完成

服務端配置
WEB層建立Controller
@Controller
@RequestMapping(path="/commodity")
public class CommodityController {
    @Autowired
    AddCommodityService   addCommodityService;
    @Autowired
private static final Logger logger = LoggerFactory.getLogger("CommodityController.class");
    @ResponseBody
    @RequestMapping(path="/upload/editor/img")
    //RequestParam中的屬性名稱要和前端定義的一致,上面說明了.所以寫"img"
    //使用List<MultipartFile>進行接收
    //返回的是一個Dto類,後面會說明,使用@ResponseBody會將其轉換為Json格式資料
    public ImgResultDto uploadEditorImg(@RequestParam("img") List<MultipartFile> list) {    
        //這裡是我在web中定義的兩個初始化屬性,儲存目錄的絕對路徑和相對路徑,你們可以自定義    
        String imgUploadAbsolutePath = request.getServletContext().getInitParameter("imgUploadAbsolutePath");
        String imgUploadRelativePath = request.getServletContext().getInitParameter("imgUploadRelativePath");

      //服務曾處理資料,返回Dto
        ImgResultDto imgResult
                = addCommodityService.upLoadEditorImg(list, imgUploadAbsolutePath, 
                                                imgUploadRelativePath,1);
            return imgResult;           
    }

}

服務層建立Service類
服務層建立Service介面類

public interface AddCommodityService {
    /**
     * 上傳商品圖片
     * @param files
     */
    ImgResultDto upLoadEditorImg(List<MultipartFile> list,
            String UploadAbsolutePath,
            String UploadRelativePath,
            int commodityId);
}

服務層建立Service介面實現類
這裡需要注意的是儲存地址,我是儲存在專案路徑下,有的會儲存在檔案系統根目錄下,比如windows可能是D://xxx/xx,linux是/xx/xx,那麼返回給客戶端的地址就會不一樣.需要根據實際情況設定

public class AddCommodityServiceImpl extends BaseService  implements AddCommodityService{
    @Autowired
    private CommodityMapper commodityMapper;
    @Autowired
    CommodityImageMapper commodityImageMapper;
    @Autowired
    private DruidDataSource dataSource; 
    @Autowired
    private SqlSessionFactoryBean sqlSessionFactory;
/**
     * 圖片上傳處理
     */
    @Override
    public ImgResultDto upLoadEditorImg(List<MultipartFile> list,
            String UploadAbsolutePath,
            String UploadRelativePath,
            int commodityId) {

        //獲取當前登入的管理員
        //CmsAdmin admin = (CmsAdmin) SessionUtils.getSession("currenLogintAdmin");
        CmsAdmin admin = new CmsAdmin("測試使用者");
        //工程絕對路徑
        String imgUploadAbsolutePath = UploadAbsolutePath;
        //工程相對路徑
        String imgUploadRelativePath = UploadRelativePath;
        logger.debug("files.length = " + list.size() );
        ImgResultDto imgResultDto = new ImgResultDto();
        //這裡定
        String[] urlData = new String[5];
        int index = 0;
        try {
            for(MultipartFile img : list) {
              //獲取原始檔名,比如你上傳的是 圖片.jpg,則fileName=圖片.jpg
                String fileName = img.getOriginalFilename();
                if(fileName == "") {
                    continue;
                }
                logger.debug("file  name = " + fileName);
                String finalPath = imgUploadAbsolutePath + imgUploadRelativePath;  //絕對路徑 + 相對路徑
                //為了保證檔名不一致,因此檔名稱使用當前的時間戳和4位的隨機數,還有原始檔名組成
                //覺得實際的企業開發不應當使用原始檔名,否則上傳者使用一些不好的名字,對於下載者就不好了.
                //這裡為了除錯方便,可以加上.
                String finalFileName =  (new Date().getTime()) + Math.round(Math.random() * 1000)  //檔名動態部分
                                    + fileName; //檔名 原始檔名        
                File newfile = new File( finalPath + finalFileName);
                logger.debug("建立資料夾 = " + newfile.mkdirs() +  "  path = " + newfile.getPath());
                logger.debug("" + newfile.getAbsolutePath());
                //儲存檔案到本地
                img.transferTo(newfile);
                logger.debug("上傳圖片成功");
                //持久化到資料庫
                CommodityImage commodityImage = new  CommodityImage(commodityId, imgUploadRelativePath,
                        finalFileName,(byte)(0),admin.getLoginJobnum(), new Date());

                commodityImageMapper.insert(commodityImage);
                logger.debug("資料庫寫入圖片成功");  
                //這裡的路徑是專案路徑+檔案路徑+檔名稱
                //這麼寫不是規範的做法,專案路徑應是放在前端處理,只需要傳送相對路徑和檔名稱即可,專案路徑由前端加上.
                urlData[index++] = "http://localhost:8080/lanmei-cms/"+imgUploadRelativePath + finalFileName;
                logger.debug("index = " + index 
                        + "  url = " + urlData[0]);
                //設定異常代號
                imgResultDto.setErrno(0);
            }
            imgResultDto.setData(urlData);
            //返回Dto
            return imgResultDto;
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            return imgResultDto;
        }

    }

}

Dto編寫
Dto 只是一個普通的pojo類,沒有業務方法,只有屬性和構造器,getter and setter.主要用於層間傳輸資料,更詳細的說明自行百度.

public class ImgResultDto<T> {

    private int  errno;//錯誤程式碼

    private String[] data;//存放資料
    //構造器
    //getter and setter

前端接收處理
新增 customInsert: function (insertImg, result, editor)這段程式 
result是返回的json資料 
因為上面只是上傳了一張圖片,儲存在陣列索引0裡 
因此通過下面獲取圖片地址. 
var url = result.data[0];

    // 上傳圖片 hook 
    uploadImgHooks: {

        before: function before(xhr, editor, files) {
            // 圖片上傳之前觸發

            // 如果返回的結果是 {prevent: true, msg: 'xxxx'} 則表示使用者放棄上傳
            // return {
            //     prevent: true,
            //     msg: '放棄上傳'
            // }
        },
        success: function success(xhr, editor, result) {
            // 圖片上傳並返回結果,圖片插入成功之後觸發
            console.log("插入圖片成功 success result = " + result.errno + "  path = " + result.data[0] );
        },
        fail: function fail(xhr, editor, result) {
            console.log(" fail result = " + result.errno + "  path = " + result.data[0] );
            // 圖片上傳並返回結果,但圖片插入錯誤時觸發
        },
        error: function error(xhr, editor) {
            // 圖片上傳出錯時觸發
            console.log("error result = " + result.errno + "  path = " + result.data[0] );
        },
        timeout: function timeout(xhr, editor) {
            // 圖片上傳超時時觸發
            console.log("timeout result = " + result.errno + "  path = " + result.data );
        },

       // 如果伺服器端返回的不是 {errno:0, data: [...]} 這種格式,可使用該配置 
        //--------------新增這段程式------------------
        customInsert: function (insertImg, result, editor) {
            // 圖片上傳並返回結果,自定義插入圖片的事件(而不是編輯器自動插入圖片!!!)
            // insertImg 是插入圖片的函式,editor 是編輯器物件,result 是伺服器端返回的結果

            // 舉例:假如上傳圖片成功後,伺服器端返回的是 {url:'....'} 這種格式,即可這樣插入圖片:

            //-----------修改這裡------------------
            //獲取返回的圖片地址
            var url = result.data[0];

            insertImg(url);

            console.log("插入圖片 url = " + url );
            // result 必須是一個 JSON 格式字串!!!否則報錯
        }
    },

    // 是否上傳七牛雲,預設為 false
    qiniu: false

};

總結
  本文說明了如何在Java WEB專案中使用富文字編輯器wangEditor,包括前端配置和後端處理.僅說明其簡單的用法,業務也未考慮的很周詳.更多功能擴充套件請看官方的說明. 
  專案的完整程式請看藍莓商城專案,後面我會陸續完善.
參考:https://blog.csdn.net/u011676300/article/details/80345152