基于springboot跟七牛云整合的ueditor

发布时间:2019-05-06
技术:springboot2.0.5.RELEASE + maven3.0.5 + jdk1.8

概述

UEditor 是由百度「FEX前端研发团队」开发的所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码。开源的代码将图片上传到webapp下面的目录下,现整合springboot将图片上传到七牛云存储服务。

详细

一、运行效果

image.png

二、实现过程

 1.下载编辑器

   到官网下载 UEditor 最新版:[官网地址]

 2.将ue的js跟css文件引入到springboot的resources下的static文件夹下,如下图所示:

image.png 

3.在resources下的templates文件下创建ue.html,代码如下:

<!DOCTYPE html>
<html xmlns:th="http://www.springframework.org/schema/jdbc">
<head>
    <meta charset="UTF-8"/>
    <title>ueditor源码版本</title>
    <style>
        #editor {
            width: 1024px;
            height: 500px;
        }
    </style>
</head>
<body>
跳转:<a href="/ueNoResource">jar包引入百度编辑器源码版本</a><br>

<div id="editor" type="text/plain"></div>
<script th:src="@{/ueditor/ueditor.config.js}"></script>
<script th:src="@{/ueditor/ueditor.all.min.js}"></script>
<script th:src="@{/ueditor/lang/zh-cn/zh-cn.js}"></script>
<script>
    UE.getEditor('editor');
</script>
</body>
</html>

4.注册一个七牛云账号

   登录到控制台创建一个云存储服务

 image.png

新建一个test的Bucket识别符的存储空间名称

image.png

在个人中心创建密钥:

image.png

5.在application.yml配置七牛云的相关配置

image.png


6.创建读取七牛云配置的类,代码如下:

@ConfigurationProperties(prefix = "ue", ignoreInvalidFields = true)
public class UdeitorProperties {

    /**
     * config.json 路径
     */
    private String configFile;

    /**
     * ueditor服务器统一请求接口路径
     */
    private String serverUrl;

    private Map<String, String> qiniu;

    public String getConfigFile() {
        return configFile;
    }

    public void setConfigFile(String configFile) {
        this.configFile = configFile;
    }

    public String getServerUrl() {
        return serverUrl;
    }

    public void setServerUrl(String serverUrl) {
        this.serverUrl = serverUrl;
    }

    public Map<String, String> getQiniu() {
        return qiniu;
    }

    public void setQiniu(Map<String, String> qiniu) {
        this.qiniu = qiniu;
    }
}

7.创建七牛云上传图片工具类QiniuUtils

public class QiniuUtils {

    public static UdeitorProperties properties;


    /**
     * 文件上传
     *
     * @param file     上传的文件
     * @param fileName 自定义文件名
     * @return java.lang.String
     */
    public static String upload(MultipartFile file, String fileName) {
        String zoneStr = properties.getQiniu().get("zone");
        Zone zone = getByName(zoneStr);
        Configuration cfg = new Configuration(zone);
        UploadManager uploadManager = new UploadManager(cfg);
        String accessKey = properties.getQiniu().get("accessKey");
        String secretKey = properties.getQiniu().get("secretKey");
        String bucket = properties.getQiniu().get("bucket");
        try {
            ByteArrayInputStream byteInputStream = new ByteArrayInputStream(file.getBytes());
            Auth auth = Auth.create(accessKey, secretKey);
            String upToken = auth.uploadToken(bucket);
            try {
                Response response = uploadManager.put(byteInputStream, fileName, upToken, null, null);
                //解析上传成功的结果
                DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
                return properties.getQiniu().get("cdn") + putRet.key;
            } catch (QiniuException ex) {
                return null;
            }
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * base64图片上传
     *
     * @param content  图片内筒
     * @param fileName 自定义文件名
     * @return java.lang.String
     */
    public static String upload(String content, String fileName) {
        String zoneStr = properties.getQiniu().get("zone");
        Zone zone = getByName(zoneStr);
        String accessKey = properties.getQiniu().get("accessKey");
        String secretKey = properties.getQiniu().get("secretKey");
        String bucket = properties.getQiniu().get("bucket");
        String url = zone.getUpBackupHttp(new ZoneReqInfo(accessKey, bucket)) + "/putb64/" + "-1" + "/key/" + UrlSafeBase64.encodeToString(fileName);
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        RequestBody rb = RequestBody.create(null, content);
        Request request = new Request.Builder().
                url(url).
                addHeader("Content-Type", "application/octet-stream")
                .addHeader("Authorization", "UpToken " + upToken)
                .post(rb).build();
        OkHttpClient client = new OkHttpClient();
        okhttp3.Response response = null;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        DefaultPutRet putRet = new Gson().fromJson(response.body().charStream(), DefaultPutRet.class);
        if (putRet.key == null) {
            return null;
        }
        return properties.getQiniu().get("cdn") + putRet.key;
    }

    /**
     * @param prefix 文件前缀
     * @param index  从第几个开始
     * @param size   返回条数
     * @param total  总条数
     * @return 文件列表
     */
    public static List<String> listFile(String prefix, int index, int size, Total total) {
        // 构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.zone0());
        String accessKey = properties.getQiniu().get("accessKey");
        String secretKey = properties.getQiniu().get("secretKey");
        String bucket = properties.getQiniu().get("bucket");
        Auth auth = Auth.create(accessKey, secretKey);
        BucketManager bucketManager = new BucketManager(auth, cfg);
        // 每次迭代的长度限制,最大1000,推荐值 1000
        int limit = 1000;
        // 指定目录分隔符,列出所有公共前缀(模拟列出目录效果)。缺省值为空字符串
        String delimiter = "";
        // 列举空间文件列表
        BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(bucket, prefix, limit, delimiter);
        FileInfo[] items = null;
        // 只列举最近的1000个文件多了也不利于展示
        if (fileListIterator.hasNext()) {
            //处理获取的file list结果
            items = fileListIterator.next();
        }
        if (items == null) {
            return null;
        }
        total.setTotal(items.length);
        if (index < 0 || index > items.length) {
            return null;
        }
        return Arrays.stream(items).skip(index).limit(size).map(fileInfo -> properties.getQiniu().get("cdn") + fileInfo.key).collect(Collectors.toList());
    }

    /**
     * 根据名称获取对应的上传区域
     *
     * @param name zone name
     * @return com.qiniu.common.Zone
     */
    static Zone getByName(String name) {
        Zone zone = null;
        switch (name) {
            case "zone0":
                zone = Zone.zone0();
                break;
            case "zone1":
                zone = Zone.zone1();
                break;
            case "zone2":
                zone = Zone.zone2();
                break;
            case "zoneNa0":
                zone = Zone.zoneNa0();
                break;
            case "zoneAs0":
                zone = Zone.zoneAs0();
                break;
            default:
                throw new RuntimeException("百度编辑七牛云zone配置错误,https://developer.qiniu.com/kodo/sdk/1239/java#server-upload");
        }
        return zone;
    }
}

8.修改ueditor上传图片的java源代码为七牛云方式

public final class Base64Uploader {

    public static State save(String content, Map<String, Object> conf) {
        byte[] data = decode(content);
        long maxSize = ((Long) conf.get("maxSize")).longValue();
        if (!validSize(data, maxSize)) {
            return new BaseState(false, AppInfo.MAX_SIZE);
        }
        String suffix = FileType.getSuffix("JPG");
        String savePath = PathFormat.parse((String) conf.get("savePath"),
                (String) conf.get("filename"));
        savePath = savePath + suffix;
        String url = QiniuUtils.upload(content, savePath);
        if (url == null) {
            return new BaseState(false, AppInfo.FAILED_CREATE_FILE);
        }
        State storageState = new BaseState();
        storageState.putInfo("url", url);
        storageState.putInfo("type", suffix);
        storageState.putInfo("original", "");
        return storageState;
    }

    private static byte[] decode(String content) {
        return Base64.decodeBase64(content);
    }

    private static boolean validSize(byte[] data, long length) {
        return data.length <= length;
    }

}
public class BinaryUploader {

    public static final State save(HttpServletRequest request,
                                   Map<String, Object> conf) {
        if (!ServletFileUpload.isMultipartContent(request)) {
            return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT);
        }
        MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
        String fileName = (String) conf.get("fieldName");
        if (fileName == null) {
            return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
        }
        MultipartFile file = mRequest.getFile(fileName);
        if (file.isEmpty()) {
            return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA);
        }
        String savePath = (String) conf.get("savePath");
        String originFileName = file.getOriginalFilename();
        String suffix = FileType.getSuffixByFilename(originFileName);
        originFileName = originFileName.substring(0,
                originFileName.length() - suffix.length());
        savePath = savePath + suffix;
        savePath = PathFormat.parse(savePath, originFileName);
        long maxSize = ((Long) conf.get("maxSize")).longValue();
        if (maxSize < file.getSize()) {
            return new BaseState(false, AppInfo.MAX_SIZE);
        }
        if (!validType(suffix, (String[]) conf.get("allowFiles"))) {
            return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE);
        }
        String url = QiniuUtils.upload(file, savePath);
        if (url == null) {
            return new BaseState(false, AppInfo.FAILED_CREATE_FILE);
        }
        State storageState = new BaseState();
        storageState.putInfo("url", url);
        storageState.putInfo("type", suffix);
        storageState.putInfo("original", originFileName + suffix);
        return storageState;
    }

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

三、项目结构图

image.pngimage.png

四、补充

 ueditor是开源可自行修改源码,可以将图片存储在绝对路径、七牛云存储、阿里云存储服务等等,是一个很好用的富文本编辑框。

本实例支付的费用只是购买源码的费用,如有疑问欢迎在文末留言交流,如需作者在线代码指导、定制等,在作者开启付费服务后,可以点击“购买服务”进行实时联系,请知悉,谢谢
手机上随时阅读、收藏该文章 ?请扫下方二维码