CKEditor 5图片的上传方式

CKEditor 5图片的上传方式

图片贴入正文支持的方式
  • 从剪切板贴入
  • 直接从文件系统中拖拽贴入
  • 通过图片按钮选择文件贴入
插入图片后的工作过程
  • 用户插入图片
  • 编辑器使用一个暂时的图片占住该位置
  • 编辑器向服务器上传该图片
  • 图片上传完成,服务器返回该图片在服务器的url路径
  • 编辑器从服务器下载该图片,替换掉暂时的图片
  • 图片插入完成
编辑器上传文件的方式

主要有如下两种:

  • 将图片上传到CKEditor提供的云服务上
  • 将图片上传到我们自己的提供的服务器上
使用CKEditor Cloud Service
  • 按照官方教程,注册一个云账号
  • 创建CKEditor时加上如下配置,其中的url是注册账号后得到的
  • 这样正文中的图片就保存在CKEditor的服务上,要拿到该图片时得保证能够连上服务器
ClassicEditor
    .create( document.querySelector( '#editor' ), {
        cloudServices: {
            tokenUrl: 'https://example.com/cs-token-endpoint',
            uploadUrl: 'https://your-organization-id.cke-cs.com/easyimage/upload/'
        }
    } )
    .then( ... )
    .catch( ... );
上传到自定义服务器 - 前端配置

上传到自定义服务器在前端需要做的工作实在是非常少了,只需要按照如下配置即可,指定自定义服务器的地址。

ClassicEditor
   .create(document.querySelector("#editor"), {
       toolbar: ["heading", "|", "alignment:left", "alignment:center", "alignment:right", "alignment:adjust", "|", "bold", "italic", "blockQuote", "link", "|", "bulletedList", "numberedList", "imageUpload", "|", "undo", "redo"],
       ckfinder: {
           uploadUrl: "http://localhost:8090/Floyd/attachment/uploadImage.do"
       }
   })
   .then(editor => {
       myEditor = editor;
   })
   .catch(error => {
       console.error(error);
   });

编辑器会自动进行上传,其需要服务器返回一个JSON数组,包含两个字段:uploaded(true / false)和url(相对路径)。举个例子如下。若没有返回内容或返回内容uploaded不为true,则会出现上传失败的情况。

["uploaded":"true", "url":"image-path..."]
上传到自定义服务器 - 后端配置(SpringMVC接收)

我是按照如下逻辑进行接收的

  • 在Spring配置中指定文件接收的Resolver(采用注解方式进行配置就是在配置类中声明一个Bean)
@Bean
public MultipartResolver multipartResolver() throws IOException {
    CommonsMultipartResolver resolver = new CommonsMultipartResolver();
    resolver.setUploadTempDir(new FileSystemResource("temp/"));

    return resolver;
}
  • Controller中使用@RequestPart(“upload”)注解直接将接收到的文件转换为MultipartFile对象。CKEditor上传图片的parameter name为”upload”,这是我使用浏览器抓包抓到的。
@RequestMapping("/uploadImage.do")
@ResponseBody
public Map<String, String> receiveImage(@RequestPart("upload") MultipartFile file, HttpServletRequest request) {
    return attachmentService.ckEditorUploadImage(file, request);
}
  • 对MultipartFile进行处理,直接调用其transferTo()将该文件转存到指定文件中。再将该文件的服务器路径返回即可
@Service("attachmentService")
public class AttachmentServiceImpl implements AttachmentService{

    private static final String CK_IMAGE_PATH = File.separator + "uploadImage";

    public Map<String, String> ckEditorUploadImage(MultipartFile file, HttpServletRequest request) {
        if(file==null || "".equals(file.getOriginalFilename().trim())) {
            return generateResult(false, "#");
        }
        String originalName = file.getOriginalFilename();
        // generate file name
        String localFileName = System.currentTimeMillis() + "-" + originalName;
        // get project path
        String projectRealPath = request.getSession().getServletContext().getRealPath("");
        // get the real path to store received images
        String realPath = projectRealPath + CK_IMAGE_PATH;
        File imageDir = new File(realPath);
        if(!imageDir.exists()) {
            imageDir.mkdirs();
        }

        String localFilePath = realPath + File.separator + localFileName;
        try {
            file.transferTo(new File(localFilePath));
        } catch (IllegalStateException e) {
            e.printStackTrace();
            // log here
        } catch (IOException e) {
            e.printStackTrace();
            // log here
        }
        String imageContextPath = request.getContextPath() + "/uploadImage" + "/" + localFileName;
        // log here + 
        System.out.println("received file original name: " + originalName);
        System.out.println("stored local file name: " + localFileName);
        System.out.println("file stored path: " + localFilePath);
        System.out.println("returned url: " + imageContextPath);
        // log here -
        return generateResult(true, imageContextPath);
    }

    private Map<String, String> generateResult(boolean uploaded, String relativeUrl){
        Map<String, String> result = new HashMap<String, String>();
        result.put("uploaded", uploaded + "");
        result.put("url", relativeUrl);

        return result;
    }
}
上传到自定义服务器 - 后端配置(普通方式接收)

采用commons-fileupload包提供的方式进行接收,(这里提供:官方指导手册, 我整理的简易教程)。
如下代码中需要注意的是,获取的FileItem中,只对FieldName为”upload”的进行解析,其余item并不是我们需要的数据,如图所示,Request Payload下的三段数据分别被解析成三个FileItem,很显然我们只需要第一个即可。
这里写图片描述

public Map<String, String> ckEditorUploadImage(HttpServletRequest request) {
    // judge if the request is multi part
    if(ServletFileUpload.isMultipartContent(request)) {
        // create a factory for disk-based file items
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // get the servlet default temp dir, and set it as multi part temp dir
        ServletContext context = request.getServletContext();
        File tempDir = (File) context.getAttribute("javax.servlet.context.tempdir");
        factory.setRepository(tempDir);
        // set size threshold, if multipart file is larger than the threshold, it will be 
        // stored in temp dir
        factory.setSizeThreshold(100000000);

        // create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload(factory);
        // set single file size limit: 10MB
        upload.setFileSizeMax(1024*1024*10);
        // set whole request size limit: 100MB
        upload.setSizeMax(1024*1024*100);

        // parse the request
        List<FileItem> items = null;
        try {
            items = upload.parseRequest(request);
        } catch (FileUploadException e) {
            e.printStackTrace();
            // log here
        }

        // processing File Item
        Iterator<FileItem> iter = items.iterator();
        String localFileName = null;
        while(iter.hasNext()) {
            FileItem item = iter.next();
            if(!"upload".equals(item.getFieldName())) {
                continue;
            }
            String originalName = item.getName();
            localFileName = System.currentTimeMillis() + "-" + originalName;
            String localFilePath = context.getRealPath(CK_IMAGE_PATH) + File.separator + localFileName;
            File localFile = new File(localFilePath);
            try {
                if(!localFile.getParentFile().exists()) {
                    localFile.getParentFile().mkdirs();
                }
                if(!localFile.exists()) {
                    localFile.createNewFile();
                }
                item.write(localFile);
            } catch (IOException e) {
                e.printStackTrace();
                // log here
            } catch (Exception e) {
                e.printStackTrace();
                // log here
            }
        }

        String imageContextPath = request.getContextPath() + CK_IMAGE_PATH + File.separator + localFileName;
     // log here + 
        System.out.println("stored local file name: " + localFileName);
        System.out.println("returned url: " + imageContextPath);
        // log here -
        return generateResult(true, imageContextPath);
    }
    return generateResult(false, "/");
}
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值