word貼上圖片到ckeitor

擇優軟體發表於2021-04-16

1.4.2之後官方並沒有做功能的改動,1.4.2在word複製這塊沒有bug,其他版本會出現手動無法轉存的情況

本文使用的後臺是Java。前端為Jsp(前端都一樣,後臺如果語言不通得自己做 Base64編碼解碼)

因為公司業務需要支援IE8 ,網上其實有很多富文字框,效果都很好。

例如www.wangEditor.com 但試了一圈都不支援IE8 。

所以回到Ueditor,由於官方沒有維護,新的neuditor 也不知道什麼時候能支援word自動轉存,只能自己想辦法。

如果沒有必要,不建議使用ueditor。我也是沒有辦法。

改動過後的外掛只適合IE8。

這裡要說明的一點是百度官方的編輯器不支援word圖片批量轉存,貼上word後需要手動選擇圖片再進行上傳一次操作。網上找到的大部分的示例都是這個操作。如果需要自動批量上傳word圖片的話可以使用WordPaster這個控制元件。

1.IE設定

在受信任站點裡新增信任網站。

這裡本機測試使用的直接是 localhost

因為需要讀取客戶端的檔案,所以需要設定允許訪問資料來源。

ActiveXObject設定可以去網上參考,這裡不列舉了。

前面的

到這裡 IE 的準備工作完成了。

修改ueditor.all.js關鍵程式碼

14006行附近,如果是其他版本的ueditor,在功能正常的情況下,可以拷貝下面程式碼。

var imgPath = attrs.src;

var imgUrl = attrs.src;

if (navigator.appName === ‘Microsoft Internet Explorer’) { //判斷是否是IE瀏覽器

if (navigator.userAgent.match(/Trident/i) && navigator.userAgent.match(/MSIE 8.0/i)) { //判斷瀏覽器核心是否為Trident核心IE8.0

    var realPath = imgPath.substring(8, imgPath.length);

    var filename = imgPath.substring(imgPath.lastIndexOf('/') + 1, imgPath.length);

    var result = UploadForIE.saveAttachment(filename, realPath);

    if (result) {

        var json = eval('(' + result + ')');

        imgUrl = json.url;

    }

}

}

img.setAttr({

width: attrs.width,

height: attrs.height,

alt: attrs.alt,

word_img: attrs.src,

src: imgUrl,

'style': 'background:url(' + (flag ? opt.themePath + opt.theme + '/images/word.gif': opt.langPath + opt.lang + '/images/localimage.png') + ') no-repeat center center;border:1px solid #ddd'

})

uploadForIE.js。

var UploadForIE = {

// 儲存到xml附件,並且通過ajax 上傳

saveAttachment: function(upload_filename, localFilePath) {

    //後臺接受圖片儲存的方法。

    var upload_target_url = "uploadImg";

    var strTempFile = localFilePath;

    // 建立XML物件,組合XML文件資料

    var xml_dom = UploadForIE.createDocument();

    xml_dom.loadXML('<?xml version="1.0" encoding="GBK" ?> <root/>');

    // 建立ADODB.Stream物件

    var ado_stream = new ActiveXObject("adodb.stream");

    // 設定流資料型別為二進位制型別

    ado_stream.Type = 1; // adTypeBinary

    // 開啟ADODB.Stream物件

    ado_stream.Open();

    // 將本地檔案裝載到ADODB.Stream物件中

    ado_stream.LoadFromFile(strTempFile);

    // 獲取檔案大小(以位元組為單位)

    var byte_size = ado_stream.Size;

    // 設定資料傳輸單元大小為1KB

    var byte_unit = 1024;

    // 獲取檔案分割資料單元的數量

    var read_count = parseInt((byte_size / byte_unit).toString()) + parseInt(((byte_size % byte_unit) == 0) ? 0 : 1);

    // 建立XML元素節點,儲存上傳檔名稱

    var node = xml_dom.createElement("uploadFilename");

    node.text = upload_filename.toString();

    var root = xml_dom.documentElement;

    root.appendChild(node);

    // 建立XML元素節點,儲存上傳檔案大小

    var node = xml_dom.createElement("uploadFileSize");

    node.text = byte_size.toString();

    root.appendChild(node);

    // 建立XML元素節點,儲存上傳檔案內容

    for (var i = 0; i < read_count; i++) {

        var node = xml_dom.createElement("uploadContent");

        // 檔案內容編碼方式為Base64

        node.dataType = "bin.base64";

        // 判斷當前儲存的資料節點大小,根據條件進行分類操作

        if ((parseInt(byte_size % byte_unit) != 0) && (i == parseInt(read_count - 1))) {

            // 當資料包大小不是資料單元的整數倍時,讀取最後剩餘的小於資料單元的所有資料

            node.nodeTypedValue = ado_stream.Read();

        } else {

            // 讀取一個完整資料單元的資料

            node.nodeTypedValue = ado_stream.Read(byte_unit);

        }

        root.appendChild(node);

    }

    // 關閉ADODB.Stream物件

    ado_stream.Close();

    delete ado_stream;

    // 建立Microsoft.XMLHTTP物件

    // var xmlhttp = new ActiveXObject("microsoft.xmlhttp");

    var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHttp");

    // 開啟Microsoft.XMLHTP物件

    xmlhttp.open("post", upload_target_url, false);

    // 使用Microsoft.XMLHTP物件上傳檔案

    xmlhttp.send(xml_dom);

    var state = xmlhttp.readyState;

    var success_state = true;

    if (state != 4) {

        success_state = false;

    }

    var result = xmlhttp.responseText;

    delete xmlhttp;

    return result;

},

// 建立DOMdocuemnt

createDocument: function() {

    var xmldom;

    var versions = ["MSXML2.DOMDocument.6.0", "MSXML2.DOMDocument.5.0", "MSXML2.DOMDocument.4.0", "MSXML2.DOMDocument.3.0", "MSXML2.DOMDocument"],

    i,

    len;

    for (i = 0, len = versions.length; i < len; i++) {

        try {

            xmldom = new ActiveXObject(versions[i]);

            if (xmldom != null) break;

        } catch(ex) {

            //跳過

            alert("建立document物件失敗!");

        }

    }

    return xmldom;

}

}

UEditorAction儲存圖片方法

@RequestMapping(“/uploadImg”)

public void uploadADO(HttpServletRequest request, HttpServletResponse response) {

    String path1 = request.getContextPath();

    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() +path1;

    String rootPath = request.getServletContext().getRealPath("/");

    // 設定資料傳輸單元大小為1KB

    int unit_size = 1024;

    // 初始化xml檔案大小(以位元組為單位)

    int xmlFileSize = 0;

    // 初始化上傳檔名稱(完整檔名)

    String xmlFilename = "";

    // 初始化上傳檔案儲存路徑(絕對物理路徑)

    String xmlFilepath = "";

    // 宣告檔案儲存位元組陣列

    byte[] xmlFileBytes = null;

    try {

        // 初始化 SAX 序列xml檔案解析器

        SAXBuilder builder = new SAXBuilder();

        Document doc = builder.build(request.getInputStream());

        Element eRoot = doc.getRootElement();

        // 獲取上傳檔案的完整名稱

        Iterator it_name = eRoot.getChildren("uploadFilename").iterator();

        if (it_name.hasNext()) {

            xmlFilename = ((Element) it_name.next()).getText();

        }

        //存放的相對路徑目錄

        String  relativePath = "/temp/"+EditorUtil.getToday()+"/";

        xmlFilepath = rootPath+ relativePath;

        // 獲取上傳檔案的大小

        Iterator it_size = eRoot.getChildren("uploadFileSize").iterator();

        if (it_size.hasNext()) {

            xmlFileSize = Integer.parseInt(((Element) it_size.next())

                    .getText());

            if (xmlFileSize > 0) {

                int unit_count = 0;

                // 為儲存檔案內容的位元組陣列分配儲存空間

                xmlFileBytes = new byte[xmlFileSize];

                // 迴圈讀取檔案內容,並儲存到位元組陣列中

                Iterator it_content = eRoot.getChildren("uploadContent")

                        .iterator();

                while (it_content.hasNext()) {

                    // 初始化Base64編碼解碼器

                    BASE64Decoder base64 = new BASE64Decoder();

                    byte[] xmlNodeByteArray = base64

                            .decodeBuffer(((Element) it_content.next())

                                    .getText());

                    if (xmlNodeByteArray.length >= unit_size) {

                        // 讀取一個完整資料單元的資料

                        System.arraycopy(xmlNodeByteArray, 0, xmlFileBytes,

                                unit_count * unit_size, unit_size);

                    } else {

                        // 讀取小於一個資料單元的所有資料

                        System.arraycopy(xmlNodeByteArray, 0, xmlFileBytes,

                                unit_count * unit_size, xmlFileSize

                                        % unit_size);

                    }

                    // 繼續向下讀取檔案內容

                    unit_count++;

                }

            }

        }

        // 儲存路徑

        File path = new File(xmlFilepath);

        if(!path.exists()){

            path.mkdirs();

        }

        // 儲存檔案 word貼上圖片的名稱

        File file = new File(path,xmlFilename);

        // 建立檔案輸入輸出流

        FileOutputStream fos = new FileOutputStream(file);

        // 寫入檔案內容

        fos.write(xmlFileBytes);

        fos.flush();

        // 關閉檔案輸入輸出流

        fos.close();

        ReturnUploadImage rui = new ReturnUploadImage();

        rui.setTitle(xmlFilename);//這裡需要設定檔名稱如:xxx.jpg

        rui.setOriginal(xmlFilename);//這裡需要設定檔名稱如:xxx.jpg

        rui.setState("SUCCESS");

        rui.setUrl(basePath +relativePath+xmlFilename);

        JSONObject json = new JSONObject(rui);

        String result = json.toString();//這邊就是為了返回給UEditor做的格式轉換

        response.getWriter().write(result);

    } catch (Exception e) {

        e.printStackTrace();

    }

}

優化後的程式碼:

upload.jsp

<%@ page language=”java” import=”java.util.*” pageEncoding=”utf-8”%>

<%@ page contentType=”text/html;charset=utf-8”%>

<%@ page import = “Xproer.*” %>

<%@ page import=”org.apache.commons.lang.StringUtils” %>

<%@ page import=”org.apache.commons.fileupload.*” %>

<%@ page import=”org.apache.commons.fileupload.disk.*” %>

<%@ page import=”org.apache.commons.fileupload.servlet.*” %>

<%out.clear();

/*

更新記錄:

    2013-01-25 取消對SmartUpload的使用,改用commons-fileupload元件。因為測試發現SmartUpload有記憶體洩露的問題。

*/

//String path = request.getContextPath();

//String basePath = request.getScheme()+”://“+request.getServerName()+”:”+request.getServerPort()+path+”/“;

String uname = “”;// = request.getParameter(“uid”);

String upass = “”;// = request.getParameter(“fid”);

// Check that we have a file upload request

boolean isMultipart = ServletFileUpload.isMultipartContent(request);

FileItemFactory factory = new DiskFileItemFactory();

ServletFileUpload upload = new ServletFileUpload(factory);

//upload.setSizeMax(262144);//256KB

List files = null;

try

{

files = upload.parseRequest(request);

}

catch (FileUploadException e)

{// 處理檔案尺寸過大異常

out.println("上傳檔案異常:"+e.toString());

return;

}

FileItem imgFile = null;

// 得到所有上傳的檔案

Iterator fileItr = files.iterator();

// 迴圈處理所有檔案

while (fileItr.hasNext())

{

// 得到當前檔案

imgFile = (FileItem) fileItr.next();

// 忽略簡單form欄位而不是上傳域的檔案域(<input type="text" />等)

if(imgFile.isFormField())

{

    String fn = imgFile.getFieldName();

    String fv = imgFile.getString();

    if(fn.equals("uname")) uname = fv;

    if(fn.equals("upass")) upass = fv;

}

else

{

    break;

}

}

Uploader up = new Uploader(pageContext,request);

up.SaveFile(imgFile);

String url = up.GetFilePathRel();

out.write(url);

response.setHeader(“Content-Length”,url.length()+””);//返回Content-length標記,以便控制元件正確讀取返回地址。

%>

剩下的後臺功能和js參考下載檔案中的UEditorAction 和 uploadForIE.js。

下面是我安裝的依賴pom結構,可以根據自己的進行調整。

        <groupId>com.baidu</groupId>

        <artifactId>ueditor</artifactId>

        <version>1.1.0</version>

    </dependency>

基於springboot 和idea ,這裡只提取了自動轉存功能出來,功能還沒測試,git程式碼沒做公開,等後續測試好了再公開。

可以先使用csdn下載檢視程式碼。

pom裡引用了ueditor.jar

需要根據各自情況安裝jar包

1.4.2中的jar包版本是1.1.0

mvn install:install-file -DgroupId=com.baidu -DartifactId=ueditor -Dversion=1.1.0 -Dpackaging=jar -Dfile=\ueditor\jsp\lib\ueditor-1.1.0.jar

執行

UeditorApplication的main方法

然後訪問localhost:8088/ueditor/ 就可以測試了。

完成後的效果:

圖片自動批量上傳,不需要手動一張張選擇圖片上傳,使用者體驗比百度ueditor自帶的更好,傳圖效率更高。

上傳成功後,圖片地址自動替換成伺服器地址

圖片自動儲存在伺服器中

詳細資料可以參考這篇文章:

blog.ncmem.com/wordpress/2019/08/12...

討論群:223813913

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章