Cách tích hợp Ckfinder vào Ckeditor trong project Spring Boot Java
Trong bài viết này mình sẽ hướng dẫn tích hợp Ckfinder và Ckeditor trong project Spring Boot Java. Mình sẽ dùng Ckfinder 2 do Ckfinder 3 chỉ hỗ trợ cho PHP và ASP.NET mà không hỗ trợ cho Java.
Đối với với những web developer việc ứng dụng các WYSIWYG editor vào việc quản trị nội dung cho website dường như là điều bắt buộc. Người dùng có thể dễ dàng cập nhật và định dạng nội dung theo ý muốn một cách dễ dàng như dùng MS Word.
Hiện tại có rất nhiều WYSIWYG editor được các nhà phát triển website sử dụng xem tại đây. Top 10 Jquery HTML5 WYSIWYG Plugins Editor
Giới thiệu Ckeditor
CKEditor (còn gọi là FCKeditor) là một trình soạn thảo mã nguồn mở theo kiểu WYSIWYG (tay làm – mắt thấy) của CKSource.
Cũng giống các trình soạn thảo dành cho web khác, CKEditor sử dụng JavaScript là nền tảng, riêng việc tương tác với server thì CKEditor sử dụng các ngôn ngữ phổ biến sau: ASP, ASP.NET, ColdFusion, Java, JavaScript, Perl, PHP và Python.
CKEditor tương thích với hầu hết các trình duyệt Internet, gồm có: Internet Explorer 6.0+ (Windows), Firefox 2.0+, Safari3.0+, Google Chrome (Windows), Opera 9.50+…
Giới thiệu Ckfinder
CKfinder là 1 trình quản lý file, nó cho phép chúng ta quản lý file, folder trên server bao gồm phân quyền sử dụng, upload file từ client. Hiện tại nếu bạn chỉ sử dụng CKEditor thì chức năng upload ảnh từ client và chèn vào bài viết không sử dụng được
.
Hướng dẫn tích hợp Ckfinder vào Ckeditor trong Spring Boot Java
Vào phần chính nào, hầu hết đa số trên mạng có rất nhiều hướng dẫn tích hợp Ckfinder vào Ckeditor trên PHP, ASP.NET. Thậm chí là Java nhưng hầu như chỉ hướng dẫn tích hợp Ckfinder cho Java web JSP hay Spring Framework với web.xml. Ngay cả document của trang chủ Ckfinder cũng chỉ hướng dẫn theo dạng web.xml. Vì thế mình quyết định viết bài Hướng dẫn tích hợp Ckfinder vào Ckeditor trong Spring Boot Java.
Các công nghệ sử dụng:
- Spring Boot + Thymeleaf
Công cụ yêu cầu:
- Ckfinder 2
- Ckeditor 3
- Eclipse + Plugin spring suite tool
Quá trình làm gồm các bước cụ thể dưới đây! Để chi tiết bạn nên xem video cuối bài !
Tải thư viện Ckfinder và Ckeditor cần thiết
Download Ckfinder java
Download Ckeditor
Cấu trúc thư mục
Tạo Spring Boot project
Eclipse bạn đã cài đặt Plugin spring suite tool. File > New > Spring Starter Project.
Next, sau đó chọn Thymeleaf và Web. Sau đó chọn Finish.
Tích hợp thư viện vào Spring Boot project (pom, static, lib)
Sau khi tải 2 thư viện phía trên về, bạn hãy giải nén ra. Copy 2 folder cần thiết vào thư mục static trong project spring boot:
- ckeditor trong ckeditor_4.8.0_basic
- ckfinder trong ckfinder_java_2.6.2.1\ckfinder\_source\CKFinder for Java\WebApp\src\main\webapp
Copy file file config.xml trong ckfinder_java_2.6.2.1\ckfinder\_source\CKFinder for Java\WebApp\src\main\webapp\WEB-INF và thư mục static.
Đồng thời bạn tạo thư mục uploadmedia trong thư mục static.
Sau đó bạn import CKFinderJava-2.6.2.1.war vào eclipse và lấy 1 số thư viện jar sau:
Sau đó bỏ vào thư mục lib nằm ở ngoài project.
Sau đó copy lib vào spring boot project.
File pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qlam</groupId>
<artifactId>ckspringbootqlam</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ckspringbootqlam</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--CKFinder start -->
<dependency>
<groupId>com.ckeditor</groupId>
<artifactId>ckeditor-java-core</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>com.finder</groupId>
<artifactId>fileeditor</artifactId>
<version>2.6.2.1</version>
<scope>system</scope>
<systemPath>${basedir}/lib/CKFinderPlugin-FileEditor-2.6.2.1.jar</systemPath>
</dependency>
<dependency>
<groupId>com.finder</groupId>
<artifactId>imgresize</artifactId>
<version>2.6.2.1</version>
<scope>system</scope>
<systemPath>${basedir}/lib/CKFinderPlugin-ImageResize-2.6.2.1.jar</systemPath>
</dependency>
<dependency>
<groupId>com.finder</groupId>
<artifactId>watermark</artifactId>
<version>2.6.2.1</version>
<scope>system</scope>
<systemPath>${basedir}/lib/CKFinderPlugin-Watermark-2.6.2.1.jar</systemPath>
</dependency>
<dependency>
<groupId>com.finder</groupId>
<artifactId>ckfinder</artifactId>
<version>2.6.2.1</version>
<scope>system</scope>
<systemPath>${basedir}/lib/CKFinder-2.6.2.1.jar</systemPath>
</dependency>
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
<scope>system</scope>
<systemPath>${basedir}/lib/thumbnailator-0.4.8.jar</systemPath>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<!--CKFinder end -->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Tạo class Cấu hình project
Tạo package com.qlam.demo.config
Trong này sẽ có 3 file dùng để cấu hình như sau:
File CKFinderConfig.java dùng để đọc file ckfinder.xml
package com.qlam.demo.config;
import com.ckfinder.connector.configuration.Configuration;
import com.ckfinder.connector.configuration.Events;
import com.ckfinder.connector.utils.PathUtils;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.servlet.ServletConfig;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Scanner;
public class CKFinderConfig extends Configuration {
public CKFinderConfig(ServletConfig servletConfig) {
super(servletConfig);
}
@Override
public void init() throws Exception {
DefaultResourceLoader loader = new DefaultResourceLoader();
Resource resource = loader.getResource(this.xmlFilePath);
Class<?> clazz = getClass().getSuperclass();
Field field = clazz.getDeclaredField("lastCfgModificationDate");
Method method = clazz.getDeclaredMethod("clearConfiguration");
method.setAccessible(true);
method.invoke(this);
field.setAccessible(true);
field.set(this, System.currentTimeMillis());
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(resource.getInputStream());
doc.normalize();
Node node = doc.getFirstChild();
if (node != null) {
NodeList nodeList = node.getChildNodes();
//Duyet qua .xml
for (int i = 0; i < nodeList.getLength(); ++i) {
Node childNode = nodeList.item(i);
if (childNode.getNodeName().equals("enabled"))
this.enabled = Boolean.valueOf(childNode.getTextContent().trim()).booleanValue();
if (childNode.getNodeName().equals("baseDir")) {
if (servletConf.getInitParameter("baseDir") == null) { //baseDir cua application.prop la null
this.baseDir = childNode.getTextContent().trim(); //lay the ben ckfinder.xml, khi do phai thiet lap ben ckfinder.xml
} else { //nguoc lai lay ben application.prop
this.baseDir = servletConf.getInitParameter("baseDir");
}
this.baseDir = PathUtils.escape(this.baseDir);
this.baseDir = PathUtils.addSlashToEnd(this.baseDir);
}
if (childNode.getNodeName().equals("baseURL")) {
if (servletConf.getInitParameter("baseURL") == null) {
this.baseURL = childNode.getTextContent().trim();
} else {
this.baseURL=servletConf.getInitParameter("baseURL")+"/public/image/";
}
this.baseURL = PathUtils.escape(this.baseURL);
this.baseURL = PathUtils.addSlashToEnd(this.baseURL);
}
if (childNode.getNodeName().equals("licenseName"))
this.licenseName = childNode.getTextContent().trim();
if (childNode.getNodeName().equals("licenseKey"))
this.licenseKey = childNode.getTextContent().trim();
String value;
if (childNode.getNodeName().equals("imgWidth")) {
value = childNode.getTextContent().trim();
value = value.replaceAll("//D", "");
try {
this.imgWidth = Integer.valueOf(value);
} catch (NumberFormatException var13) {
this.imgWidth = null;
}
}
if (childNode.getNodeName().equals("imgQuality")) {
value = childNode.getTextContent().trim();
value = value.replaceAll("//D", "");
method = clazz.getDeclaredMethod("adjustQuality", new Class[]{String.class});
method.setAccessible(true);
this.imgQuality = Float.parseFloat(method.invoke(this, value).toString());
}
if (childNode.getNodeName().equals("imgHeight")) {
value = childNode.getTextContent().trim();
value = value.replaceAll("//D", "");
try {
this.imgHeight = Integer.valueOf(value);
} catch (NumberFormatException var12) {
this.imgHeight = null;
}
}
if (childNode.getNodeName().equals("thumbs")) {
method = clazz.getDeclaredMethod("setThumbs", new Class[]{NodeList.class});
method.setAccessible(true);
method.invoke(this, childNode.getChildNodes());
}
if (childNode.getNodeName().equals("accessControls")) {
method = clazz.getDeclaredMethod("setACLs", new Class[]{NodeList.class});
method.setAccessible(true);
method.invoke(this, childNode.getChildNodes());
}
if (childNode.getNodeName().equals("hideFolders")) {
method = clazz.getDeclaredMethod("setHiddenFolders", new Class[]{NodeList.class});
method.setAccessible(true);
method.invoke(this, childNode.getChildNodes());
}
if (childNode.getNodeName().equals("hideFiles")) {
method = clazz.getDeclaredMethod("setHiddenFiles", new Class[]{NodeList.class});
method.setAccessible(true);
method.invoke(this, childNode.getChildNodes());
}
if (childNode.getNodeName().equals("checkDoubleExtension"))
this.doubleExtensions = Boolean.valueOf(childNode.getTextContent().trim()).booleanValue();
if (childNode.getNodeName().equals("disallowUnsafeCharacters"))
this.disallowUnsafeCharacters = Boolean.valueOf(childNode.getTextContent().trim()).booleanValue();
if (childNode.getNodeName().equals("forceASCII"))
this.forceASCII = Boolean.valueOf(childNode.getTextContent().trim()).booleanValue();
if (childNode.getNodeName().equals("checkSizeAfterScaling"))
this.checkSizeAfterScaling = Boolean.valueOf(childNode.getTextContent().trim()).booleanValue();
Scanner sc;
if (childNode.getNodeName().equals("htmlExtensions")) {
value = childNode.getTextContent();
sc = (new Scanner(value)).useDelimiter(",");
while (sc.hasNext()) {
String val = sc.next();
if (val != null && !val.equals(""))
this.htmlExtensions.add(val.trim().toLowerCase());
}
}
if (childNode.getNodeName().equals("secureImageUploads"))
this.secureImageUploads = Boolean.valueOf(childNode.getTextContent().trim()).booleanValue();
if (childNode.getNodeName().equals("uriEncoding"))
this.uriEncoding = childNode.getTextContent().trim();
if (childNode.getNodeName().equals("userRoleSessionVar"))
this.userRoleSessionVar = childNode.getTextContent().trim();
if (childNode.getNodeName().equals("defaultResourceTypes")) {
value = childNode.getTextContent().trim();
sc = (new Scanner(value)).useDelimiter(",");
while (sc.hasNext())
this.defaultResourceTypes.add(sc.next());
}
if (childNode.getNodeName().equals("plugins")) {
method = clazz.getDeclaredMethod("setPlugins", new Class[]{Node.class});
method.setAccessible(true);
method.invoke(this, childNode);
}
if (childNode.getNodeName().equals("basePathBuilderImpl")) {
method = clazz.getDeclaredMethod("setBasePathImpl", new Class[]{String.class});
method.setAccessible(true);
method.invoke(this, childNode.getTextContent().trim());
}
}
}
method = clazz.getDeclaredMethod("setTypes", new Class[]{Document.class});
method.setAccessible(true);
method.invoke(this, doc);
field = clazz.getDeclaredField("events");
field.setAccessible(true);
field.set(this, new Events());
this.registerEventHandlers();
}
}
File CKFinderServletConfig.java dùng để thiết lập thuộc tính trên file application.properties
package com.qlam.demo.config;
import com.ckfinder.connector.ConnectorServlet;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CKFinderServletConfig {
@Value("${ckeditor.storage.image.path}")
private String baseDir;
@Value("${ckeditor.access.image.url}")
private String baseURL;
@Bean
public ServletRegistrationBean connectCKFinder(){
ServletRegistrationBean registrationBean=new ServletRegistrationBean(new ConnectorServlet(),"/ckfinder/core/connector/java/connector.java");
registrationBean.addInitParameter("XMLConfig","classpath:/static/ckfinder.xml");
registrationBean.addInitParameter("debug","false");
registrationBean.addInitParameter("configuration","com.qlam.demo.config.CKFinderConfig");
//ckfinder.xml
registrationBean.addInitParameter("baseDir",baseDir);
registrationBean.addInitParameter("baseURL",baseURL);
return registrationBean;
}
}
File WebMvcConfig.java dùng để thiết lập đường dẫn thư viện và file upload theo Spring MVC
package com.qlam.demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// file:D:\\data\\file\\image\\
registry.addResourceHandler("/public/image/**").addResourceLocations("classpath:/static/uploadmedia/");
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("/ckfinder/**").addResourceLocations("classpath:/static/ckfinder/");
super.addResourceHandlers(registry);
}
}
File application.properties
# ===============================
# THYMELEAF
# ===============================
spring.thymeleaf.cache=false
# ===============================
# DATASOURCE
# ===============================
# Set here configurations for the database connection
# config dir so that ckeditor and ckfinder loading to media upload, write null so that use ckfinder.xml
ckeditor.storage.image.path=src/main/resources/static/uploadmedia/
ckeditor.access.image.url=http://localhost:8080
Xử lý với Controller class
Tạo package com.qlam.demo.controller
Chúng ta cần 1 class Controller để chạy trang chủ.
File QController.java đơn giản là mình cho nó dùng giao diện file adpost.html để hiện cho trang chủ.
package com.qlam.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class QController {
@GetMapping("/")
public String home() {
return "adpost";
}
}
Thiết kế giao diện với thymeleaf engine
Mình tạo giao diện web đơn giản chia làm 2 phần:
- Dùng Ckeditor tích hợp Ckfinder khi upload ảnh
- Chạy Ckfinder khi nhấn một nút
Trong phần src/main/resources/templates tạo file adpost.html
File adpost.html
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="head">
<meta charset="utf-8" />
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>Ckfinder</title>
</head>
<body>
<div id="page-content-wrapper">
<h1 id="home" class="text-center font-bold mt-1">Integrate
ckfinder into ckeditor in spring boot project</h1>
<h2>ShareEverythings.com</h2>
<!-- Section: Create Page -->
<section class="section mt-5 container-fluid">
<!-- First row -->
<div class="row">
<!-- First col -->
<div class="col-lg-6">
<h3>A. Integrate ckfinder into ckeditor</h3>
<!-- Second card -->
<div class="card mb-r">
<textarea name="content" id="content"></textarea>
</div>
<!-- /.Second card -->
</div>
<!-- /.First col -->
<div class="col-lg-6">
<h3>B. Ckfinder Button</h3>
<div class="avatar">
<img id="imgpreview"
src="https://yt3.ggpht.com/-f6NCDKG2Ukw/AAAAAAAAAAI/AAAAAAAAAAA/MqMm3rgmqCY/s48-c-k-no-mo-rj-c0xffffff/photo.jpg"
class="img-fluid" style="max-width: 300px; max-height: 300px;" />
</div>
<div class="file-field">
<p>
<strong id="xImagePath">Selected Image URL</strong><br /> <input
class="btn btn-primary btn-sm waves-effect waves-light"
type="button" value="Browse Image"
onclick="BrowseServer( 'Images:/', 'xImagePath' );" />
</p>
</div>
<p>Note: You should select square image !</p>
</div>
</div>
<!-- /.First row -->
</section>
<!-- /.Section: Create Page -->
</div>
<script src="ckeditor/ckeditor.js"></script>
<script src="ckfinder/ckfinder.js"></script>
<script>
CKEDITOR
.replace(
'content',
{
filebrowserBrowseUrl : 'ckfinder/ckfinder.html',
filebrowserImageBrowseUrl : 'ckfinder/ckfinder.html?type=Images',
filebrowserFlashBrowseUrl : 'ckfinder/ckfinder.html?type=Flash',
filebrowserUploadUrl : 'ckfinder/core/connector/java/connector.java?command=QuickUpload&type=Files',
filebrowserImageUploadUrl : 'ckfinder/core/connector/java/connector.java?command=QuickUpload&type=Images',
filebrowserFlashUploadUrl : 'ckfinder/core/connector/java/connector.java?command=QuickUpload&type=Flash'
});
/*Avatar start*/
function BrowseServer(startupPath, functionData) {
// You can use the "CKFinder" class to render CKFinder in a page:
var finder = new CKFinder();
// The path for the installation of CKFinder (default = "/ckfinder/").
finder.basePath = '../';
//Startup path in a form: "Type:/path/to/directory/"
finder.startupPath = startupPath;
// Name of a function which is called when a file is selected in CKFinder.
finder.selectActionFunction = SetFileField;
// Additional data to be passed to the selectActionFunction in a second argument.
// We'll use this feature to pass the Id of a field that will be updated.
finder.selectActionData = functionData;
// Name of a function which is called when a thumbnail is selected in CKFinder. Preview img
// finder.selectThumbnailActionFunction = ShowThumbnails;
// Launch CKFinder
finder.popup();
}
// This is a sample function which is called when a file is selected in CKFinder.
function SetFileField(fileUrl, data) {
document.getElementById(data["selectActionData"]).innerHTML = this
.getSelectedFile().name;
document.getElementById("imgpreview").src = fileUrl;
}
/*Avatar end*/
</script>
</body>
</html>
Chạy project
Kết quả thành công!
Nhờ các plugin bạn có thể thay đổi kích thước ảnh.
Video chi tiết Hướng dẫn tích hợp Ckfinder vào Ckeditor trong Spring Boot Java
Download Full Project Java
Lưu ý: nếu bạn build jar war file lỗi thì hãy thêm dòng sau vào mục plugins của pom.xml
nhé:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
Em chào anh,
Cảm ơn anh vì bài viết khá hữu ích. Trong phần cấu hình:
“` @Value(“${ckeditor.storage.image.path}”)
private String baseDir;
“`
Em nghĩ nên sử dụng “`ClassLoader“` để load đường dẫn đến folder “`uploadmedia“` thì tiện hơn. Khi deploy sẽ không phải config lại.
“`
private ClassLoader classLoader = CKFinderServletConfig.class.getClassLoader();
// @Value(“${ckeditor.storage.image.path}”)
private String baseDir = classLoader.getResource(“static/uploadmedia”).getPath() + “/”;
“`
A cho em hỏi chút, trong class “`CKFinderConfig“ dựa vào mà a biết cách để config như vậy. A có thể cho em tài liệu tham khảo/chỉ giúp em được không ạ. Em cảm ơn 😀
Cảm ơn bạn khuyến nghị, cái config Mình dựa vào ckfinder.xml ấy, tìm cách parse đọc file đó sang object thôi!
Thanks b, nhưng mình thấy rằng mất khá nhiều bước để parse từ xml rồi transfer qua lại như vậy.
Vì cách đấy thấy phụ thuộc vào nhiều APIs -> tighed coupling.
Thay vào đó sao không config “XMLConfig” trỏ trực tiếp đến “config.xml” -> Code sẽ ngắn hơn và nhanh hơn rất nhiều mà 😀
Oh, nếu bạn đã viết cách trực tiếp đó bạn có thể chia sẽ lên đây không để giúp bài mình hoàn thiện hơn?
Bạn có thể chỉnh “CKFinderServletConfig” như sau:
”
@Configuration
public class CKFinderServletConfig {
private ClassLoader classLoader = CKFinderServletConfig.class.getClassLoader();
private String ckfinderXMLPath = classLoader.getResource(“static”).getPath() + “/ckfinder.xml”;
@Bean
public ServletRegistrationBean connectCKFinder() {
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new ConnectorServlet(),
“/ckfinder/core/connector/java/connector.java”);
registrationBean.addInitParameter(“XMLConfig”, ckfinderXMLPath);
registrationBean.addInitParameter(“debug”, “false”);
return registrationBean;
}
}
”
Khi deploy bạn có thể config đường dẫn trỏ đến “uploadmeadia” như sau:
”
E:\workspace\your-project\target\classes\static\uploadmedia
http://localhost:8080/public/resources/
”
(Nếu muốn có thể bind value trực tiếp luôn)
Ah mà trong cách của bạn, tuy rằng app run OK nhưng vẫn báo Exception: “Configuration file could not be found under specified location” 😉
Mình cũng vậy!
Hi admin, em có làm theo tài liệu nhưng khi chạy lên nó báo “không hồi đấp dk file xml” và báo ko tìm thấy “/ckfinder/core/connector/java/connector.java”.
Em cũng chưa hiểu là link java ở đâu a.
em có tải bản code về chạy thì thấy vẫn dk, nhưng ckeditor ko full dk toolBar. Cao thủ nào giải thích cho em với ạ.
Connector.java thuộc thư viện CKFinder-2.6.2.1.jar. Bạn đã copy thư viện lib jar chưa ? Có full toolbar cho ckeditor hay không là tùy vào lúc đầu bạn chọn tải bản Full package ở trang chủ ckeditor ấy!
It was not possible to properly load the XML response from the web server.
Raw response from the server:
{“timestamp”:1525409041533,”status”:500,”error”:”Internal Server Error”,”exception”:”java.lang.Exception”,”message”:”Configuration wasn’t initialized correctly. Check server logs.”,”path”:”/ckfinder/core/connector/java/connector.java”}
em copy CKFinder-2.6.2.1.jar lib ở project của bác vào rồi. mà trong file jar chỉ có file class thôi bác. file java em ko biết tại sao lại ở đấy nhỉ.
lỗi này do nó không tìm thấy file trong server bạn kiểm tra lại file config.xml và class xử lý nó có giống bên mình ko? Còn jar có file .class sẽ được java dịch ngược lại .java nên thông thường bạn ko thấy file .java
Bạn ơi, mấy file config trong package config có file config dưới dạng xml không bạn?
có nha bạn, nó nằm trong thư mục resource
Nếu dùng chỉ dùng Spring MVC và không có ServletRegistrationBean của Spring Boot thì làm sao cấu hình ạ !
có nhiều cách cấu hình như: Annotation, Programmatic Registration, XML Configuration, File .properties. Bạn tham khảo: https://www.baeldung.com/register-servlet
Tks anh !
sao k down đc src về vậy anh
em skip ap quảng cáo 5 giây sẽ qua link Mediafire nha !
Dùng CKFinder free sẽ có trademark, nếu mua thì cần 17$.
Mình có đọc custom image upload adapter của CK nhưng complicated.
Bạn có biết solution nào cho popular rich editor nào mà support image upload easy/free ko?
Bạn tham khảo https://shareeverythings.com/lap-trinh/javascript/top-10-jquery-html5-wysiwyg-plugins-editor/
thank bạn nhiều
Cho mình hỏi tại sao khi tải ảnh lên ở button browse image lại không hiển thị ảnh thế.
Do thư mục bạn chưa update file upload. Bạn phải cài đặt refresh poll cho eclipse, bạn xem đoạn cuối video !
nó vẫn cảnh báo như này bạn ơi:
“Configuration file could not be found under specified location”.
Có thể phiên bản ckfinder 2 này khá cũ nên xuất hiện vài lỗi cấu hình.
Muốn dùng ckeditor nhập và đưa dữ liệu lên database sử dụng kiểu dữ liệu gì anh
Bạn có thể dùng nvarchar(MAX)
Cho em hỏi tại sao phần demo project em tải về run thì thanh toolbar trong ckeditor lại không có phần ảnh. Làm sao để nó hiện giống như video. Thanks a
Em muốn lưu ảnh vào folder khác với cả khi lưu ảnh thì đặt tên ảnh là 1 chuỗi ngẫu nhiên thì config ở đâu ạ?