Ckeditor 5 + springboot (4): file upload by springboot

Time:2021-4-8

In this series of articles, I’ll show you how to use the ckeditor editor in spring boot application. The content includes the basic environment construction, file upload, spring data JPA data persistence, ckeditor5 installation, ckeditor image upload, ckeditor insert video, get / set ckeditor content, etc.

Ckeditor 5 + springboot (4): file upload by springboot

In this chapter, the main content is to achieve the image upload function in springboot, including the upload path setting, image path mapping and upload business code writing.

File upload

The so-called file upload is to transfer the client’s resources to the server through the network, and its essence is Io stream operation. The server reads the client data through IO stream, analyzes the data, obtains the target file data, and stores the data in the server disk.

Introduce dependency

To upload files, you need to import the required dependency package into the project. Here we only import Commons fileUpload and Commons IO dependency packages. Usually, commons fileUpload and Commons IO need to be used together, which encapsulates a large number of functions for operating file upload, which can help us simplify the writing of file upload code. open pom.xml Configuration file, and add the following configuration:

<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.6</version>
</dependency>

Storage path

As we mentioned above, the essence of file upload is to store the client data to the server disk through IO stream. Therefore, we need to plan a storage space on the disk of the server to store the files uploaded by the client. Here, I store the files uploaded by the client in the images folder under the classpath of the current project.

First of all, in the com.ramostear.ckeditor Create a consts class in the. Common package, and then get the classpath of the current project through the classpathresource class. The code is as follows:

package com.ramostear.ckeditor.common;

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import java.io.IOException;

public class Consts {

    public static String FILE_STORAGE_ROOT = getRootPath();

    private static String getRootPath(){
        try {
            Resource resource = new ClassPathResource("");
            return resource.getFile().getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

In the code, the obtained classpath is assigned to the public static constant file_ STORAGE_ Root, the constant will be used in image path mapping and file upload business code.

Upload configuration

In general, the data of the client can be transferred to the server through the form, but if it is big file data such as pictures, the server will not be able to parse these data directly (if it is a picture file, it can also transfer the binary text to the server after transcoding the pictures through Base64). Therefore, we need to configure a special file for parsing the uploaded files of the client In addition, if you upload image files, you usually need to display these images after successful upload. In springboot, the client cannot directly load these files, which requires us to manually map the image address.

Next, we will introduce how to configure the parameters related to file upload in springboot. The simplest way to configure is to inherit the webmvcconfigurationsupport class from the configuration class, and then rewrite the corresponding method. First, the file parser. Here we instantiate a Commons multipart resolver as the parser for uploading files, and then set the size and character encoding of the files it allows to upload. The code is as follows:

@Bean
public CommonsMultipartResolver multipartResolver(){
    CommonsMultipartResolver resolver = new CommonsMultipartResolver();
    resolver.setMaxUploadSize(600000000);
    resolver.setDefaultEncoding("UTF-8");
    return resolver;
}

Tips:

In the code, the setmaxuploadsize() method is used to limit the maximum size of the uploaded file, in bytes. If you do not want to limit the size of the uploaded file, you can set the value to – 1, and the default value is – 1.

Finally, for example, to display the uploaded image in the client browser, we need to override the addresourcehandlers () method in the webmvcconfigurationsupport class, and then map the image upload path we defined. The code is as follows:

@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**")
        .addResourceLocations("classpath:/static/")
        .addResourceLocations("file:"+ Consts.FILE_STORAGE_ROOT+"/images");
    super.addResourceHandlers(registry);
}

In the above code, map the image address under “classpath] / static /” and file upload path to “/ *”, for example, the image storage path uploaded to the server is “C] / ckeditor5 springboot / images/ demo.png ”, then the request address of the image in the client browser is: http://localhost :8080/ demo.png “。 The complete configuration class is as follows:

package com.ramostear.ckeditor.config;

import com.ramostear.ckeditor.common.Consts;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

@Configuration
public class MvcConfiguration extends WebMvcConfigurationSupport {

    @Bean
    public CommonsMultipartResolver multipartResolver(){
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        resolver.setMaxUploadSize(600000000);
        resolver.setDefaultEncoding("UTF-8");
        return resolver;
    }

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/")
                .addResourceLocations("file:"+ Consts.FILE_STORAGE_ROOT+"/images/");
        super.addResourceHandlers(registry);
    }
}

Tips:

Don’t forget to add @ configuration annotation of configuration class and @ bean annotation of configuration method.

Realize file upload

After all the above steps are ready, we will realize the function that the server obtains the file uploaded by the client and saves it to the disk. First, define a FileManager interface class, and provide file upload and delete methods. The code is as follows:

package com.ramostear.ckeditor.service;

import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.util.Collection;

public interface FileManager {

    String upload(CommonsMultipartFile multipartFile);

    boolean remove(String url);

    void remove(Collection<String> urls);
}

The upload () method is used to write the file uploaded by the client to the specified upload directory, and the remove () method is called when deleting the content. Next, in the FileManagerImpl.java Class.

upload

For file upload, we must first obtain the file storage path, then rename the uploaded file, and finally write the data of the uploaded file to the target file. We will use the transferto() method provided by commonsmultipartfile to read and write the file. The code is as follows:

@Override
public String upload(CommonsMultipartFile multipartFile) {
    String storageRoot = Consts.FILE_STORAGE_ROOT+ File.separator+"images";
    String path = "";
    String suffix = Objects.requireNonNull(multipartFile.getOriginalFilename())
        .substring(multipartFile.getOriginalFilename().lastIndexOf("."));
    String fileName = SIMPLE_DATE_FORMAT.format(new Date())+"-"
        + UUID.randomUUID().toString().replaceAll("-","").toLowerCase()
        + suffix;
    File file = new File(storageRoot+File.separator+fileName);
    if(!file.getParentFile().exists()){
        file.getParentFile().mkdirs();
    }
    try {
        multipartFile.transferTo(file);
        path = "/"+fileName;
    }catch (IOException e){
        e.printStackTrace();
    }
    return path;
}

After the file is uploaded successfully, we need to return the relative address of the file to the upper layer.

remove

The method of deleting a file is relatively simple. Find the incoming file in the upload directory. If it is found, delete the file. Otherwise, do nothing. The code is as follows:

@Override
public boolean remove(String url) {
    String path = Consts.FILE_STORAGE_ROOT+ File.separator+"images"+url;
    File file = new File(path);
    if(file.exists() && file.isFile()){
        return file.delete();
    }
    return false;
}

FileManagerImpl.java The complete code of the class is as follows:

package com.ramostear.ckeditor.service.impl;

import com.ramostear.ckeditor.common.Consts;
import com.ramostear.ckeditor.service.FileManager;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;

@Service(value = "fileManager")
public class FileManagerImpl implements FileManager {
    private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");

    @Override
    public String upload(CommonsMultipartFile multipartFile) {
        String storageRoot = Consts.FILE_STORAGE_ROOT+ File.separator+"images";
        String path = "";
        String suffix = Objects.requireNonNull(multipartFile.getOriginalFilename())
                .substring(multipartFile.getOriginalFilename().lastIndexOf("."));
        String fileName = SIMPLE_DATE_FORMAT.format(new Date())+"-"
                + UUID.randomUUID().toString().replaceAll("-","").toLowerCase()
                + suffix;
        File file = new File(storageRoot+File.separator+fileName);
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        try {
            multipartFile.transferTo(file);
            path = "/"+fileName;
        }catch (IOException e){
            e.printStackTrace();
        }
        return path;
    }

    @Override
    public boolean remove(String url) {
        String path = Consts.FILE_STORAGE_ROOT+ File.separator+"images"+url;
        File file = new File(path);
        if(file.exists() && file.isFile()){
            return file.delete();
        }
        return false;
    }

    @Override
    public void remove(Collection<String> urls) {
        if(!CollectionUtils.isEmpty(urls)){
            urls.stream().allMatch(this::remove);
        }
    }
}

Tips:

Don’t forget to add the @ service annotation to the implementation class.

Upload controller

Finally, we use spring MVC to implement the image upload controller. According to the relevant API on the official website, ckeditor submits the file named “Upload” to the background by post request. After the background processes the data, it needs to return the data in the following format:

{
    "uploaded":true,
    "filename":"filename",
    "url":'url'
}

When the image is uploaded successfully, the value of uploaded is true, otherwise it is false.

The following is the detailed code of the upload image controller:

package com.ramostear.ckeditor.controller;

import com.alibaba.fastjson.JSONObject;
import com.ramostear.ckeditor.service.FileManager;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/upload")
public class FileUploadController {

    private final FileManager fileManager;

    FileUploadController(FileManager fileManager){
        this.fileManager = fileManager;
    }

    @PostMapping("/image")
    public JSONObject image(@RequestParam(name = "upload")CommonsMultipartFile file){
        JSONObject json = new JSONObject();
        if(file == null || file.isEmpty()){
            json.put("uploaded",false);
            json.put("url","");
            return json;
        }
        if(StringUtils.isBlank(file.getOriginalFilename()) || !isAllow(file.getOriginalFilename())){
            json.put("uploaded",false);
            json.put("url","");
            return json;
        }
        String url = fileManager.upload(file);
        if(StringUtils.isBlank(url)){
            json.put("uploaded",false);
            json.put("url","");
            return json;
        }else{
            json.put("uploaded",true);
            json.put("url",url);
            return json;
        }
    }

    private boolean isAllow(String fileName){
        String[] allowFiles = {".gif",".png",".jpg",".jpeg",".bpm",".svg"};
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        List<String> suffixList = Arrays.stream(allowFiles).collect(Collectors.toList());
        return suffixList.contains(suffix);
    }
}

The isallow () method is used to restrict the uploaded file to be image type only. In the fileuploadcontroller class, the FileManager instantiation object is injected into the fileuploadcontroller based on construction method injection, and the image upload operation is completed. In addition, the stringutils tool class and the Alibaba fastjson class are used in this class. Therefore, you also need to pom.xml Add the following dependencies to the file:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.57</version>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
</dependency>

Upload test

Because the front-end page has not been built yet, we use the browser to test the file upload function, but we can use postman to test the file upload function. Open the postman software, and then create a new request. The request method is post, and then enter it in the address bar“ http://localhost : 8080 / upload / image “; finally, in the body options bar, the data submission format is form data, the value of key is” Upload “, the type is” file “, and the value is the image to be uploaded. After configuration, click the “send” button to test. The test flow is as follows:

Ckeditor 5 + springboot (4): file upload by springboot

After the picture is uploaded successfully, we can view the picture “20200707-3ed0218d4194f4f803e710573f07390. PNG” just uploaded in the target / classes / images / directory of the project, as shown in the following figure:

Ckeditor 5 + springboot (4): file upload by springboot

In addition, we can input in the browser“ http://localhost : 8080 / 20200707-3ed0218d4194f4f803e710573f07390. PNG “to access the image just uploaded, as shown in the following figure:

Ckeditor 5 + springboot (4): file upload by springboot

Summary of this chapter

In this chapter, the detailed process of file upload using springboot is introduced in detail, and the function of file upload is tested by using postman tool. In the next chapter, we will introduce the integration of springboot and freemaker template engine.

Without the permission of the author, please do not reprint, reprint please indicate the author and source of the article.

Recommended Today

Third party calls wechat payment interface

Step one: preparation 1. Wechat payment interface can only be called if the developer qualification has been authenticated on wechat open platform, so the first thing is to authenticate. It’s very simple, but wechat will charge 300 yuan for audit 2. Set payment directory Login wechat payment merchant platform( pay.weixin.qq . com) — > Product […]