1. 程式人生 > >vue + Springboot 前後端分離整合UEditor

vue + Springboot 前後端分離整合UEditor

UEditor只提供JSP版本的後端入口程式碼。但是它提供了專案原始碼,因此我們可以根據業務需求來修改原始碼。

現在開始整合UEditor

 1、下載UEditor官網最新的jsp版本的包,下載完成解壓之後得到一個utf8-jsp的資料夾,裡面包含的內容如下

除了jsp資料夾和index.html檔案外,把所有的檔案都複製到前臺目錄下的static裡資料夾裡,如下圖:

2. 將編輯器封裝成一個元件,方便呼叫,程式碼如下:

<template>
  <div class="edit">
    <script id="editor" type="text/plain"></script>
  </div>
</template>

<script>
  import '../../static/UE/ueditor.config.js'
  import '../../static/UE/ueditor.all.js'
  import '../../static/UE/lang/zh-cn/zh-cn.js'
  export default {
    name: 'UEditor',
    data () {
      return {
        editor: null
      }
    },
    props: {
      defaultMsg: {
        type: String
      },
      config: {
        type: Object
      }
    },
    mounted() {
      const _this = this;
      this.editor = UE.getEditor('editor', this.config); // 初始化UE
    },
    methods: {
      getUEContent() { // 獲取內容方法
        return this.editor.getContent()
      }
    },
    destroyed() {
      this.editor.destroy();
    }
  }
</script>

<style lang="scss" scoped>
  .edit{
    width: 1200px;
    margin: auto;
  }
</style>

元件的使用:

<template>
  <div class="components-container">
    <div class="info">UE編輯器示例<br>需要使用編輯器時,呼叫UE公共元件即可。可設定填充內容defaultMsg,配置資訊config(寬度和高度等),可呼叫元件中獲取內容的方法。</div>
    <button @click="getUEContent()">獲取內容</button>
    <div class="editor-container">
      <mh-ue :defaultMsg=defaultMsg :config=config ref="ue"></mh-ue>
    </div>
  </div>
</template>

<script>
  import mhUe from '../components/UEditor';
  export default {
    components: {
      mhUe
    },
    data() {
      return {
        defaultMsg: '這裡是UE測試',
        config: {
          initialFrameWidth: null,
          initialFrameHeight: 350
        }
      }
    },
    methods: {
      getUEContent() {
        let content = this.$refs.ue.getUEContent();
        this.$notify({
          title: '獲取成功,可在控制檯檢視!',
          message: content,
          type: 'success'
        });
        console.log(content)
      }
    }
  };
</script>

<style lang="scss" scoped>
  .info{
    border-radius: 10px;
    line-height: 20px;
    padding: 10px;
    margin: 10px;
    background-color: #ffffff;
  }
</style>

前臺我們就先做到這裡

接下來去配置後臺

1.首先從官網上下載原始碼,下載之後解壓縮,將jsp目錄下的src中程式碼複製到專案中,然後將config.json放到專案的resources中

2. 為UEditor新建一個controller,並寫入config對映,程式碼如下:

@RestController
@RequestMapping("/mh/ueditor")
@CrossOrigin(allowCredentials = "true")
public class UeditorController {
    @RequestMapping(value="/config")
    public void config(HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("application/json");

        String rootPath = request.getSession().getServletContext().getRealPath("/");
        try {
            String exec = new ActionEnter(request, rootPath).exec();
            PrintWriter writer = response.getWriter();
            writer.write(exec);
            writer.flush();
            writer.close();
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}

3. 修改ConfigManage類的getConfigPath()方法,使其能載入config.json檔案,程式碼如下:

	private String getConfigPath () {
//		return this.parentPath + File.separator + ConfigManager.configFileName;
		/*此部分為手動修改*/
		try {
			// 需要先轉為URI再getPath(),否則專案路徑帶空格或者帶中文則無法讀取到檔案
			return this.getClass().getClassLoader().getResource("config.json").toURI().getPath();
		} catch (URISyntaxException e) {
			return null;
		}
	}

4. 轉到前臺,修改ueditor.config.js

  此時已經可以選擇圖片了,但仍然無法上傳圖片,那是因為在BinaryUploader類中無法獲取到位元組流。究其原因,SpringMVC框架對含位元組流的request進行了處理,此處傳的是處理過的request,故獲取不到位元組流。此時採用SpringMVC框架的解析器multipartResolver。所以程式碼修改如下:

package com.baidu.ueditor.upload;

import com.baidu.ueditor.PathFormat;
import com.baidu.ueditor.define.AppInfo;
import com.baidu.ueditor.define.BaseState;
import com.baidu.ueditor.define.FileType;
import com.baidu.ueditor.define.State;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import jdk.internal.util.xml.impl.Input;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

public class BinaryUploader {

	/**
	 * 修改BinaryUploader類,解決其無法獲得帶位元組流的request的問題
	 */
	public static final State save(HttpServletRequest request,
			Map<String, Object> conf) {

//		FileItemStream fileStream = null;
//		boolean isAjaxUpload = request.getHeader( "X_Requested_With" ) != null;

		if (!ServletFileUpload.isMultipartContent(request)) {
			return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);
		}

//		ServletFileUpload upload = new ServletFileUpload(
//				new DiskFileItemFactory());
//
//        if ( isAjaxUpload ) {
//            upload.setHeaderEncoding( "UTF-8" );
//        }

		try {
//			FileItemIterator iterator = upload.getItemIterator(request);
//
//			while (iterator.hasNext()) {
//				fileStream = iterator.next();
//
//				if (!fileStream.isFormField())
//					break;
//				fileStream = null;
//			}
//
//			if (fileStream == null) {
//				return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
//			}

			/*========== 新增的內容 ==========*/
			MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
			MultipartFile multipartFile = multipartRequest.getFile(conf.get("fieldName").toString());
			if (multipartFile == null) {
				return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
			}
			// 新增結束

			String savePath = (String) conf.get("savePath");
//			String originFileName = fileStream.getName();
			String originFileName = multipartFile.getOriginalFilename(); // 修改的
			String suffix = FileType.getSuffixByFilename(originFileName);

			originFileName = originFileName.substring(0,
					originFileName.length() - suffix.length());
			savePath = savePath + suffix;

			long maxSize = ((Long) conf.get("maxSize")).longValue();

			if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
				return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
			}

			savePath = PathFormat.parse(savePath, originFileName);

			String physicalPath = (String) conf.get("rootPath") + savePath;

//			InputStream is = fileStream.openStream();
			InputStream is = multipartFile.getInputStream();
			State storageState = StorageManager.saveFileByInputStream(is,
					physicalPath, maxSize);
			is.close();

			if (storageState.isSuccess()) {
				storageState.putInfo("url", PathFormat.format(savePath));
				storageState.putInfo("type", suffix);
				storageState.putInfo("original", originFileName + suffix);
			}

			return storageState;
//		} catch (FileUploadException e) {
//			return new BaseState(false, AppInfo.PARSE_REQUEST_ERROR);
		} catch (IOException e) {
		}
		return new BaseState(false, AppInfo.IO_ERROR);
	}

	private static boolean validType(String type, String[] allowTypes) {
		List<String> list = Arrays.asList(allowTypes);

		return list.contains(type);
	}
}

5.至此多圖片上傳已經成功了,但是雖然上傳成功了,但卻不能展示出來,那是因為它的圖片訪問路徑字首是前臺的路徑,而不是後臺的訪問路徑,所以我們要在後臺的config.json修改下圖片路徑字首,如下圖:

至此就可以完整展示出圖片了,但是單圖片上傳依然不行,那是因為出現了iframe跨域的問題,為解決此問題,我將原有的form.submit的表單上傳方式,更改為ajax的上傳方式;

其程式碼如下:

/**
           * 2018-10-13 改掉了ueditor原始碼,將本身的單檔案上傳的方法改為ajax上傳,主要目的是為了解決跨域的問題
           * @author [email protected]
           */
          domUtils.on(input, 'change', function() {
              if(!input.value) return;
              var loadingId = 'loading_' + (+new Date()).toString(36);
              var imageActionUrl = me.getActionUrl(me.getOpt('imageActionName'));
              var allowFiles = me.getOpt('imageAllowFiles');

              me.focus();
              me.execCommand('inserthtml', '<img class="loadingclass" id="' + loadingId + '" src="' + me.options.themePath + me.options.theme +'/images/spacer.gif" title="' + (me.getLang('simpleupload.loading') || '') + '" >');

              /!* 判斷後端配置是否沒有載入成功 *!/
              if (!me.getOpt('imageActionName')) {
                errorHandler(me.getLang('autoupload.errorLoadConfig'));
                return;
              }
              // 判斷檔案格式是否錯誤
              var filename = input.value,
                fileext = filename ? filename.substr(filename.lastIndexOf('.')):'';
              if (!fileext || (allowFiles && (allowFiles.join('') + '.').indexOf(fileext.toLowerCase() + '.') == -1)) {
                showErrorLoader(me.getLang('simpleupload.exceedTypeError'));
                return;
              }

              var params = utils.serializeParam(me.queryCommandValue('serverparam')) || '';
              var action = utils.formatUrl(imageActionUrl + (imageActionUrl.indexOf('?') == -1 ? '?' : '&') + params);
              var formData = new FormData();
              formData.append("upfile", form[0].files[0] );
              $.ajax({
                url: action,
                type: 'POST',
                cache: false,
                data: formData,
                processData: false,
                contentType: false,
                success: function (data) {
                  // data = JSON.parse(data);
                  var link, loader,
                    body = (iframe.contentDocument || iframe.contentWindow.document).body,
                    result = body.innerText || body.textContent || '';
                  link = me.options.imageUrlPrefix + data.url;

                  if(data.state == 'SUCCESS' && data.url) {
                    loader = me.document.getElementById(loadingId);
                    loader.setAttribute('src', link);
                    loader.setAttribute('_src', link);
                    loader.setAttribute('title', data.title || '');
                    loader.setAttribute('alt', data.original || '');
                    loader.removeAttribute('id');
                    domUtils.removeClasses(loader, 'loadingclass');
                  } else {
                    showErrorLoader && showErrorLoader(data.state);
                  }
                  form.reset();
                }
              });
              function showErrorLoader(title){
                if(loadingId) {
                  var loader = me.document.getElementById(loadingId);
                  loader && domUtils.remove(loader);
                  me.fireEvent('showmessage', {
                    'id': loadingId,
                    'content': title,
                    'type': 'error',
                    'timeout': 4000
                  });
                }
              }
            });

解決好跨域問題,我們還要引入jQuery檔案,依然是這個檔案,在24460行左右的程式碼中,加入下圖程式碼:

至此問題已完美解決.

可是圖片上傳到哪了,圖片被傳到了C盤的Tomcat的快取中C:\Users\hqw\AppData\Local\Temp\tomcat-docbase.112263787422681723.8111,後面的數字每次都是變動的

當我們每次重啟Tomcat時,該檔案就會被刪除,所以我們要把檔案存到磁碟中去。

1.修改檔案上傳路徑,在config.json中加入如下程式碼, 並修改imagePathFormat,

2.開啟ConfigManager.java, 加入如下程式碼

3,開啟BinaryUploader.java,修改程式碼如下:

4.加入路徑對映。開啟application.yml檔案,新增如下程式碼

web:
  upload-path: E:/

spring:
  mvc:
    static-path-pattern: /**
  resources:
    static-locations: /META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${web.upload-path}

執行專案,ueditor圖片上傳就可以完整的使用了。

相關推薦

vue + Springboot 前後分離整合UEditor

UEditor只提供JSP版本的後端入口程式碼。但是它提供了專案原始碼,因此我們可以根據業務需求來修改原始碼。 現在開始整合UEditor  1、下載UEditor官網最新的jsp版本的包,下載完成解壓之後得到一個utf8-jsp的資料夾,裡面包含的內容如下: 除了

Vue+SpringBoot 前後分離小實驗

1、概述 業務模型:員工+部門,多對一,實現增刪改查(CRUD) 後端:Spring Boot + Spring MVC + Spring REST Data 前端:Vue + axios 2、後端開發 POM依賴 <?xml version="1.

【筆記】vue+springboot前後分離實現token登入驗證和狀態儲存的簡單實現方案

簡單實現 token可用於登入驗證和許可權管理。 大致步驟分為: 前端登入,post使用者名稱和密碼到後端。 後端驗證使用者名稱和密碼,若通過,生成一個token返回給前端。 前端拿到token用vuex和localStorage管理,登入成功進入首頁。 之後前端每一次許可權操作如跳轉路由,都需要判斷是否存

Uni-app實戰專案之整合SpringBoot前後分離開發Android、iOS、小程式應用

歡迎加入課程群:571278542 課程大綱[會有細微差異,最終以錄製課程為準]: 1、成果演示 2、開發技術和工具介紹 3、建立資料庫(後臺開發3-7節) 4、環境搭建 5、欄目管理(七牛雲管理附件)

Springboot+Vue前後分離與合併方案

摘要: springboot+vue的前後端分離與合併 springboot和vue結合的方案網路上的主要有以下兩種: 1. 【不推薦】在html中直接使用script標籤引入vue和一

一分鐘搭建vue,elementui,springboot前後分離項目

javax let ddp imp ram config tps save red 1.下載 npm , node.js 2.element-ui項目下載:https://github.com/ElementUI/element-starter 3.springboot項目

一套基於SpringBoot+Vue+Shiro 前後分離 開發的程式碼生成器

一、前言 最近花了一個月時間完成了一套基於Spring Boot+Vue+Shiro前後端分離的程式碼生成器,目前專案程式碼已基本

flask+vue.js 前後分離入門教程

pla .com 數據 快樂 storage pack 輕量 沒有 www 適合對象: 對flask有一定基礎,做過簡單的flask項目。但是之前每個頁面都是通過render_template來渲染的。沒有前後端分離的項目經歷。 整理了網上“非夢nj”童鞋的9篇文章: V

SpringBoot前後分離Instant時間戳自定義解析

在SpringBoot專案中,前後端規定傳遞時間使用時間戳(精度ms). @Data public class Incident { @ApiModelProperty(value = "故障ID", example = "1") private Integer id; @ApiMo

vue+Springboot 前後資料互動(1)

最近使用 vue 的 axios 往後端傳送資料,結果一直報錯,嘗試了多種方法 如果vue專案沒有打包放在 springboot 專案下的話,需要開啟跨域支援 在 vue 專案裡 config 目錄下的 index.js 檔案,找到 proxyTable   加上 '

Vue專案 前後分離模式解決開發環境的跨域問題

在前後端分離的web開發中,我們與後臺聯調時,會遇到跨域的問題。 比如: 開發地址是 localhost:8080,需要訪問 localhost:9000 上的介面。 不同域名之間的訪問,需要跨域才能正確請求。跨域的方法很多,在 Vue-cli 建立的專案中,可以直接利用 Node.js

Django連線VUE前後分離

搭建Django參考改自here 1、建立Django專案: django-admin startproject ulb_manager 2、進入專案根目錄,建立app作為專案後端 cd ulb_manager python manage.py star

從零到一 django + vue 構建前後分離專案

(本文在win10環境下進行) django 和 vue 的優點 django的python血統,開發起來基本上是站在巨人的肩膀上,用起來順手,加上drf這個restful API 框架,SaltStack、Ansible可做配置管理,celery做任務佇列

springboot前後分離跨域同源問題

筆者最近做springboot前後端分離遇到一些問題,在這裡分享下。主要是跨域問題,導致後端無法獲取自定義請求頭, 前端後臺分開部署在不同域名,自然而然就會存在跨域問題,前端ajax的處理方式通常就是jsonp。 springboot 後端配置有如下兩種方式,二選一就好

java面試題架構篇NodeJS,Vue前後分離都是什麼鬼

1.Node.JS node.js是開源的,跨平臺的,瀏覽器之外的Js執行環境。前後端統一語言開發。主要特點 事件驅動 非同步IO 基於Google的V8引擎,V8引擎執行Javascript的速度非常快,效能非常好 單執行緒,單程序 優點: 容易學習,全棧開發-

Java Web 開發 springboot 前後分離以及身份驗證

我先接觸的前後端分離是.Net的webapi,特性路由什麼的,所以想知道java中的webapi是什麼樣的,在網上直接查java webapi 得不到類似於C# 的webapi的資料,但是查java 前後端分離,就能找到類似於C# webapi的東西。 看了一篇文章,根據文章中提供的gith

Flask & Vue 構建前後分離的應用

Flask & Vue 構建前後端分離的應用 最近在使用 Flask 製作基於 HTML5 的桌面應用,前面寫過《用 Python 構建 web 應用》,藉助於完善的 Flask 框架,可以輕鬆的構建一個網站應用。服務端的路由管理和前端模板頁面的渲染都使用 Flask 提供的 API 即可,並且由於

springboot前後分離之跨域

springmvc有多種處理跨域的方法,介紹最簡單的一種: @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addCors

dotnetcore+vue+elementUI 前後分離 三(前端篇)

                        &n

jwt,spring security ,feign,zuul,eureka 前後分離 整合 實現 簡單 許可權管理系統 與 使用者認證的實現

本例子 包含有 一下模組:  eureka 模組,充當 註冊中心角色 user-service-api 客戶端介面和實體 user-service-provider 客戶端服務提供者 user-conusmer 客戶端消費者 zuul 模組為閘道器,用來實現統一路由