SpringBoot整合Markdown实现图片上传和图片再次回显(详细步骤)

Posted yuwenS.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot整合Markdown实现图片上传和图片再次回显(详细步骤)相关的知识,希望对你有一定的参考价值。

SpringBoot整合Markdown实现图片的上传和再次回显

前期准备

  • 要有markdown的资源文件可以去 markdown官网 下载资源

  • 下载成功后文件中的目录
    在这里插入图片描述

  • 在整合的过程中再将我们需要的资源导入到项目中

效果图

编写时的效果图
编写前

再次回显的效果图
再次查看

具体实现

在数据库中建立文章表,因为是简单测试所以久只有文章id和文章内容
数据表
要导入的资源文件
在这里插入图片描述

建立SpringBoot项目并向pom.xml文件中导入jar包

	<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
        <!--thymeleaf-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>

application.yml文件的配置

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
    username: root
    password: root

mybatis:
  type-aliases-package: com.yuwen.pojo
  mapper-Locations: classpath*:mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true

实体类Article

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Article implements Serializable {
  private long id;
  private String content;
}

ArticleMapper接口和ArticleMapper.xml文件的配置

@Mapper
public interface ArticleMapper{
    //添加文章
    public boolean addArticle(Article article);
    //根据文章id查询文章
    public Article findArticleById();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

<mapper namespace= "com.yuwen.mapper.ArticleMapper" >
    <insert id="addArticle" parameterType="com.yuwen.pojo.Article">
        insert into article values (#{id},#{content})
    </insert>

    <!--因为没有传入id所以指定查询id为1的文章-->
    <select id="findArticleById" resultType="com.yuwen.pojo.Article">
        select * from article where id = 1
    </select>
</mapper>

ArticleService接口的实现类ArticleServiceImpl

@Service
public class ArticleServiceImpl implements ArticleService {
    
    @Resource
    private ArticleMapper articleMapper;
    
    /**
     * 添加文章
     * @param content 文章的内容(富文本框中的值)
     * @param request request
     * @return 添加文章成功是否成功
     */
    @Override
    public boolean addArticle(String content,HttpServletRequest request){
        Article article = new Article();
        article.setId(1); //因为没有传入id进来,所以默认设置文章id为1
        try {
            String s = CopyImg.copyImg(content, request); //通过工具类将文章中的图片保存到要保存的地址方便下次回显
            article.setContent(s);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return articleMapper.addArticle(article);
    }

    /**
     * 根据id查询文章
     * @return 查询的文章
     */
    @Override
    public Article findById() {
        return articleMapper.findArticleById();
    }
}

ArticleController类

@Controller
public class ArticleController {

    @Resource
    private ArticleService articleService;

    //显示markdown页面
    @GetMapping("/toEditor")
    public String toEditor(){
        return "editormd";
    }

    //上传图片并回显
    @ResponseBody
    @RequestMapping("/uploadImg")
    public Map<String,Object> uploadImg(HttpServletRequest request, @RequestParam(value = "editormd-image-file", required = false) MultipartFile file){
        Map<String,Object> map = new HashMap<>();
        if (file != null){
            //获取此项目的tomcat路径
            String webapp = request.getServletContext().getRealPath("/");
            try{
                //获取文件名
                String filename = file.getOriginalFilename();
                UUID uuid = UUID.randomUUID();
                String name = "";
                if (filename != null){
                    name = filename.substring(filename.lastIndexOf(".")); //获取文件后缀名
                }
                // 图片的路径+文件名称
                String fileName = "/upload/" + uuid + name;
                // 图片的在服务器上面的物理路径
                File destFile = new File(webapp, fileName);
                // 生成upload目录
                File parentFile = destFile.getParentFile();
                if (!parentFile.exists()) {
                    parentFile.mkdirs();// 自动生成upload目录
                }
                // 把上传的临时图片,复制到当前项目的webapp路径
                FileCopyUtils.copy(file.getInputStream(), new FileOutputStream(destFile));
                map.put("success",1); //设置回显的数据 0 表示上传失败,1 表示上传成功
                map.put("message","上传成功"); //提示的信息,上传成功或上传失败及错误信息等
                map.put("url",fileName); //图片回显的url 上传成功时才返回
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return map;
    }

    //添加文章信息
    @ResponseBody
    @PostMapping("/add")
    public Map<String,Object> add(String content,HttpServletRequest request){
        Map<String,Object> map = new HashMap<>();
        boolean b = articleService.addArticle(content,request);
        if (b){
            map.put("msg","添加成功");
        }else{
            map.put("msg","添加失败");
        }
        return map;
    }

    //显示文章内容
    @GetMapping("/show")
    public String show(Model model){
        Article article = articleService.findById();
        model.addAttribute("article",article);
        return "show";
    }
}

因为图片上传之后存入了磁盘当中,所以为了下次访问这张图片,需要配置虚拟路径

虚拟路径的配置这里我是把图片存入我的D盘当中

//配置虚拟路径,通过虚拟路径指向磁盘路径
@Configuration
public class MyWebAppConfigurer implements WebMvcConfigurer {
    /*
        /image/upload/** 表示虚拟路径
        file:/D:/image/upload/ 表示磁盘路径
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/image/upload/**").addResourceLocations("file:/D:/image/upload/");
        WebMvcConfigurer.super.addResourceHandlers(registry);
    }
}

在将图片上传中,因为富文本框中还有其他的内容,所以我们需要将图片拿出来,存入磁盘当中,并且将图片的路径改为我们要的虚拟路径,所以需要一个工具类来完成

工具类的实现

@Component
public class CopyImg {
    public static String copyImg(String content, HttpServletRequest request) throws IOException {
        String webapp = request.getServletContext().getRealPath("/");
        String path = "D:\\\\image";
        List<String> list = new ArrayList<String>();
        List<String> urlList = new ArrayList<String>();
        Pattern pattern = Pattern.compile("(?<=\\\\()[^\\\\)]+"); //正则表达式匹配所以括号的内容
        Matcher matcher = pattern.matcher(content);
        while(matcher.find()){
            list.add(matcher.group());
            content = content.replace(matcher.group(), "/image" + matcher.group());//将路径/upload修改为/image/upload
        }
        for (int i = 0;i < list.size();i++){
            urlList.add(webapp+list.get(i)); //找到图片在服务器中的地址,并存入list集合中
        }
        File file = null;
        File destFile = null;
        for (int i = 0;i < urlList.size();i++){
            file = new File(urlList.get(i));
            destFile = new File(path,list.get(i));
            FileCopyUtils.copy(file,destFile); //将图片从服务器中复制到我们的磁盘中
        }
        return content;
    }
}

编写文章的html页面

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8" />
    <title>Simple example - Editor.md examples</title>
    <link rel="stylesheet" th:href="@{/css/style.css}"/>
    <link rel="stylesheet" th:href="@{/css/editormd.css}"/>
    <link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon" />
</head>
<body>
<div id="layout">
    <header>
        <h1>Markdown编辑器</h1>
    </header>
    <button style="width: 50px;height: 20px" onclick="upload()">上传</button>
    <div id="editormd">
        <textarea id = "text" style="display:none;" ></textarea>
    </div>
</div>
<script th:src="@{/js/jquery.min.js}"></script>
<script th:src="@{/js/editormd.min.js}"></script>
<script>
    function upload(){
        let content = $("#text").text(); //获取富文本框中的值
        $.ajax({
            url: 'http://localhost:8080/add',
            type: 'post',
            data: {
                content : content
            },
            success:function (data){
                console.log(data);
            }
        })
    }
</script>
<script type="text/javascript">
    var testEditor;
    $(function() {
        testEditor = editormd("editormd", {
            width: "90%",
            height: 640,
            syncScrolling: "single",
            emoji: true,
            imageUpload: true, //同意图片上传
            imageFormats: ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
            imageUploadURL: "/uploadImg",       //图片上传URL 即后台的图片上传接口URL
            path: "/editormd/lib/"
        });
    });
</script>
</body>
</html>

显示文章的页面

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8" />
    <title>Simple example - Editor.md examples</title>
    <link rel="stylesheet" th:href="@{/css/style.css}"/>
    <link rel="stylesheet" th:href="@{/css/editormd.css}"/>
    <link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon" />
</head>
<body>
<div id="layout">
    <div id="test">
        <textarea以上是关于SpringBoot整合Markdown实现图片上传和图片再次回显(详细步骤)的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot整合Markdown实现图片上传和图片再次回显(详细步骤)

Vue整合Markdown组件+SpringBoot文件上传+代码差异对比

springboot整合thumbnailator实现图片压缩

Shiro整合Springboot之图片验证码实现

SpringBoot2.0集成FastDFS

SpringBoot项目整合FastDFS+Nginx实现图片上传