杰瑞科技汇

CKEditor图片上传Java如何实现?

  • 前端: CKEditor 5 (推荐,因为它更现代化、功能更强大)
  • 后端: Spring Boot (Java)
  • 图片存储: 服务器本地文件系统 (最简单的方式)

整体思路

  1. 前端配置 CKEditor: 初始化 CKEditor,并配置一个自定义的上传按钮。
  2. 前端处理上传: 当用户点击上传按钮时,通过 fetch API 将图片文件发送到我们后端创建的接口。
  3. 后端接收文件: Spring Boot 创建一个 @PostMapping 接口,接收 multipart/form-data 格式的文件。
  4. 后端处理并存储: 后端接收文件,进行校验(如大小、类型),然后将其保存到服务器的指定目录。
  5. 后端返回响应: 上传成功后,后端返回一个 JSON 响应,包含图片的访问 URL,CKEditor 会根据这个 URL 将图片插入到编辑器中。

第一步:后端实现 (Spring Boot)

我们将创建一个 Spring Boot 应用来处理文件上传。

CKEditor图片上传Java如何实现?-图1
(图片来源网络,侵删)

项目依赖 (pom.xml)

确保你的 pom.xml 包含了 Spring Web 和 Lombok(可选,用于简化代码)依赖。

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Lombok (可选,用于简化 getter/setter) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

创建文件上传目录

src/main/resources 目录下创建一个 static/uploads 目录,上传的图片将保存在这里,Spring Boot 默认会从 static 目录下提供静态文件访问。

src/
└── main/
    └── resources/
        └── static/
            └── uploads/  <-- 图片存放目录

创建文件上传配置类 (FileUploadConfig.java)

这个类用于配置文件上传的大小限制等。

package com.example.ckeditordemo.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "file.upload") // 从 application.yml 中读取配置
public class FileUploadConfig {
    private String uploadDir;
    private long maxFileSize; // 单位: bytes
    // Getters and Setters
    public String getUploadDir() {
        return uploadDir;
    }
    public void setUploadDir(String uploadDir) {
        this.uploadDir = uploadDir;
    }
    public long getMaxFileSize() {
        return maxFileSize;
    }
    public void setMaxFileSize(long maxFileSize) {
        this.maxFileSize = maxFileSize;
    }
}

application.yml 中添加配置

src/main/resources/application.yml 文件中添加以下配置:

CKEditor图片上传Java如何实现?-图2
(图片来源网络,侵删)
server:
  port: 8080
file:
  upload:
    # 上传目录,注意要和 FileUploadConfig 中的 prefix 对应
    # 这里我们指向 static/uploads 目录
    upload-dir: uploads
    # 最大文件大小,这里是 2MB
    max-file-size: 2097152

创建文件上传控制器 (FileUploadController.java)

这是核心部分,负责处理文件上传请求。

package com.example.ckeditordemo.controller;
import com.example.ckeditordemo.config.FileUploadConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
@Slf4j
@RestController
@RequestMapping("/api/upload")
public class FileUploadController {
    @Autowired
    private FileUploadConfig fileUploadConfig;
    @PostMapping(value = "/image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ResponseEntity<?> uploadImage(@RequestParam("upload") MultipartFile file) {
        try {
            // 1. 检查文件是否为空
            if (file.isEmpty()) {
                return ResponseEntity.badRequest().body("请选择一个文件。");
            }
            // 2. 检查文件大小
            if (file.getSize() > fileUploadConfig.getMaxFileSize()) {
                return ResponseEntity.badRequest().body("文件大小超过限制。");
            }
            // 3. 检查文件类型 (简单示例,只允许图片)
            String contentType = file.getContentType();
            if (contentType == null || !contentType.startsWith("image/")) {
                return ResponseEntity.badRequest().body("只允许上传图片文件。");
            }
            // 4. 获取原始文件名
            String originalFilename = file.getOriginalFilename();
            // 5. 生成新的唯一文件名,防止覆盖
            String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            String newFilename = UUID.randomUUID().toString() + fileExtension;
            // 6. 构建文件存储路径
            // 注意:fileUploadConfig.getUploadDir() 返回的是 "uploads"
            // 我们需要将其拼接成完整的服务器路径
            Path uploadPath = Paths.get("src/main/resources/static", fileUploadConfig.getUploadDir());
            // 如果目录不存在,则创建
            if (!Files.exists(uploadPath)) {
                Files.createDirectories(uploadPath);
            }
            Path destination = uploadPath.resolve(newFilename);
            // 7. 保存文件
            Files.copy(file.getInputStream(), destination);
            // 8. 返回 CKEditor 期望的响应格式
            String fileUrl = "/uploads/" + newFilename; // 静态资源访问路径
            String responseJson = String.format(
                "{\"url\":\"%s\",\"uploaded\":\"%s\"}",
                fileUrl,
                "true"
            );
            return ResponseEntity.ok(responseJson);
        } catch (IOException e) {
            log.error("文件上传失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败。");
        }
    }
}

重要说明:

  • CKEditor 的响应格式: CKEditor 5 对图片上传的响应有特定的 JSON 格式要求,成功时,它期望收到 {"url": "图片URL", "uploaded": "true"}
  • 静态资源路径: 我们将文件保存在 static/uploads 下,Spring Boot 会自动将 /uploads/... 的请求映射到这个目录,所以返回的 url 应该是 /uploads/文件名

第二步:前端实现 (CKEditor 5)

引入 CKEditor 5

你可以使用 CDN 或 npm/yarn,这里我们使用 CDN,因为它最简单。

在 HTML 页面的 <head> 中引入 CKEditor 5 的样式和脚本:

CKEditor图片上传Java如何实现?-图3
(图片来源网络,侵删)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">CKEditor 5 图片上传示例</title>
    <!-- CKEditor 5 样式 -->
    <link rel="stylesheet" href="https://cdn.ckeditor.com/ckeditor5/39.0.1/ckeditor5.css">
    <!-- 自定义样式,让编辑器占满屏幕 -->
    <style>
        body {
            font-family: sans-serif;
        }
        .editor-container {
            width: 100%;
            max-width: 1000px;
            margin: 20px auto;
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
    <h1>CKEditor 5 图片上传示例</h1>
    <div id="editor" class="editor-container"></div>
    <!-- CKEditor 5 脚本 -->
    <script src="https://cdn.ckeditor.com/ckeditor5/39.0.1/ckeditor5.js"></script>
    <!-- 初始化编辑器的脚本 -->
    <script>
        ClassicEditor
            .create(document.querySelector('#editor'), {
                // 配置项
                toolbar: {
                    items: [
                        'heading',
                        '|',
                        'bold',
                        'italic',
                        'link',
                        'bulletedList',
                        'numberedList',
                        '|',
                        'outdent',
                        'indent',
                        '|',
                        'imageUpload', // 添加图片上传按钮
                        'blockQuote',
                        'insertTable',
                        'undo',
                        'redo'
                    ]
                },
                // 图片上传配置
                image: {
                    toolbar: [
                        'imageTextAlternative',
                        'imageStyle:alignLeft',
                        'imageStyle:alignCenter',
                        'imageStyle:alignRight',
                        'imageStyle:side'
                    ],
                    // 自定义上传适配器
                    upload: {
                        // 你的后端上传接口地址
                        // 确保这个地址能被你的前端页面访问到(CORS问题)
                        // 如果前端和后端同源,一般没问题。
                        // 如果是前后端分离,后端需要配置CORS。
                        url: 'http://localhost:8080/api/upload/image'
                    }
                }
            })
            .then(editor => {
                console.log('编辑器初始化完成', editor);
            })
            .catch(error => {
                console.error('初始化编辑器时发生错误', error);
            });
    </script>
</body>
</html>

关键配置说明

  • toolbar: 在工具栏中添加了 'imageUpload',这样用户才能看到上传按钮。
  • image.upload.url: 这是最关键的配置,它告诉 CKEditor 5,当用户点击上传按钮时,应该将文件发送到哪个 URL。请将其替换为你自己的后端接口地址

第三步:处理跨域问题

如果你的前端页面(http://localhost:8081)和后端接口(http://localhost:8080)不在同一个端口下,就会遇到跨域问题,浏览器会阻止前端页面向后端接口发送请求。

解决方案:在后端添加 CORS 配置。

创建一个 CORS 配置类

package com.example.ckeditordemo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        // 允许所有来源
        config.addAllowedOrigin("*");
        // 允许所有头信息
        config.addAllowedHeader("*");
        // 允许所有方法 (GET, POST, PUT, DELETE, OPTIONS 等)
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

或者在 Controller 方法上使用 @CrossOrigin 注解 (更简单)

如果你只想让某个特定的接口支持跨域,可以直接在 Controller 方法上添加注解,这是最简单的方式。

修改 FileUploadController.java

// ... 其他 import ...
import org.springframework.web.bind.annotation.CrossOrigin;
@Slf4j
@RestController
@RequestMapping("/api/upload")
public class FileUploadController {
    // ... @Autowired 和其他代码 ...
    @PostMapping(value = "/image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    // 在这里添加 @CrossOrigin 注解
    // 允许来自 http://localhost:8081 的所有请求
    // 或者直接使用 @CrossOrigin(origins = "*") 允许所有来源
    @CrossOrigin(origins = "http://localhost:8081", allowCredentials = "true") 
    public ResponseEntity<?> uploadImage(@RequestParam("upload") MultipartFile file) {
        // ... 上传逻辑不变 ...
    }
}

注意: allowCredentials = "true" 通常用于处理包含 cookies 或认证头的请求,对于简单的文件上传,可以不加,如果遇到问题,可以尝试加上。


总结与运行

  1. 启动后端: 运行你的 Spring Boot 应用,确保服务器在 8080 端口启动。
  2. 打开前端: 在浏览器中打开你的 HTML 文件(如果你使用一个简单的 Web 服务器,VS Code 的 Live Server 插件,它可能会在 8081 或其他端口启动)。
  3. 测试:
    • 在 CKEditor 中点击图片上传按钮。
    • 选择一张本地图片。
    • 点击“上传”。
    • 观察控制台,如果成功,图片应该会直接插入到编辑器中,src 属性指向你后端返回的 URL (如 http://localhost:8080/uploads/xxxx.jpg)。

至此,你已经成功地在 Java 项目中集成了 CKEditor 5 并实现了图片上传功能,这个方案是功能完整且可扩展的,你可以根据需要进一步优化,比如将图片保存到云存储(如阿里云OSS、AWS S3)等。

分享:
扫描分享到社交APP
上一篇
下一篇