Springboot结合前端上传图片保存到数据库读取

前言

最近在做一个前后端分离系统,也是闲的无聊做个好玩的练练手。就突然想着之前想了一天的问题,前端怎么去发送图片到后端保存(不是专业前端,轻点喷),图片到底是保存在本地还是存在oss上,保存图片的方式又是什么,这些问题想到我头皮发麻。最后,还是花了一下午的时间写出来了个半成品(最后一步没保存到数据库,后期更新)。
首先我们先来看看效果图:
Springboot结合前端上传图片保存到数据库读取_第1张图片
Springboot结合前端上传图片保存到数据库读取_第2张图片
Springboot结合前端上传图片保存到数据库读取_第3张图片
虽说界面有点丑,但是也还将就吧。
接下来就直接把代码贡献给各位(后期改进点击图片上传)

思路

前端包装一个FormData参数,发送给后端接收,后端定义好实体类和文件,数据交互使用ajax,页面跳转使用Ajax,数据传递使用session。网页展示中,使用FileReader来实时预览。
可能有人问,为什么不用base64编码去保存图片信息,不为什么,因为我不喜欢。。(其实是太长了,每次测试都眼花)

实体类

由于这里是测试,所以我就定义了三个,用户名-username、密码-password、文件名-imgName

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("user") // 忽略这里,还没连接数据库。。。
public class Info {
    private Integer id;
    private String username;
    private String password;
    private String imgName;
}
前端登录层

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js">script>
    <script th:src="@{style.js}">script>
head>
<body>
<form id="form-data">
    用户名:<input type="text" name="username" placeholder="用户名"><br>
    密码:<input type="password" name="password" placeholder="密码"><br>
    头像:<input type="file" accept="*/*" name="file" id="FileImg" onchange="xmTanUploadImg(this)">
    <img src="" alt="默认头像地址(可以自己填)" id="avarimgs" style="border-radius: 50%" width="200px" height="200px">
    <input type="button" value="注册" id="registerBtn" onclick="reg()">
form>

body>
html>
function xmTanUploadImg(obj) {
    var file = obj.files[0];
    console.log("obj:" + obj);
    console.log("file:" + file);
    console.log("fileName:" + file.name)
    console.log("file.size = " + file.size);
    var reader = new FileReader();
    reader.onload = function (e) {
        console.log(e)// ProgressEvent 对象,里面的target.result就是base64编码
        console.log("成功读取....");
        var img = document.getElementById("avarimgs");
        img.src = e.target.result;
        //或者 img.src = this.result;  //e.target == this
    }
    reader.readAsDataURL(file)
}

function reg() {
    let form = new FormData($("#form-data")[0])
    console.log(form)
    $.ajax({
        //接口地址
        url: 'submit',
        type: 'POST',
        data: form,
        async: false,
        cache: false,
        contentType: false,
        processData: false,
        success:function (data) {
            console.log(data)
            console.log(data.imgName);
            sessionStorage.setItem("img_name",data.imgName);
            window.location='/info'
        }
    });
}
后端控制层
@Controller
@ResponseBody
public class FileController {

    @RequestMapping(value = "/submit", method = RequestMethod.POST)
    public Info submit(MultipartFile file,Info info)
            throws Exception {
        //这里就可以获取里面的上传过来的数据了
        //做一些存库操作,以及返回的数据
        String filename = file.getOriginalFilename();
        System.out.println(filename);
        String filePath = System.getProperty("user.dir")+"\\src\\main\\resources\\static\\img";
        if (!new File(filePath).exists()){
            new File(filePath).mkdirs();
        }
        File dest = new File(filePath + File.separator + info.getUsername()+"_"+filename);
        try {
            file.transferTo(dest);
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println(info);
        info.setImgName(info.getUsername()+"_"+filename);
        return info;
    }
}

我在后端由于要保存用户头像,所以命名为了防止冲突,直接暴力的使用用户名加上图片文件名进行保存,这样可以很大程度上保证用户的头像唯一(或者在登录的时候直接加一个判断,先保证用户名在数据库中唯一,因为我自己在设计的时候用的主要是一个别名而不是用户名,所以我就没有加)
保存目录不能直接写死路径,假如你的项目需要部署在服务器上,那么就会直接报找不到文件的错误。所以我借用了MyBatis-plus的写法,用了当前系统目录;

踩的坑
在测试的时候,由于第一次上传上去之后图片不能立即显示,需要重启服务器。这个坑折磨了我半个小时,最后看了一眼网上大佬们的做法,加一个资源映射就完美的解决了。确实,这个很nice。所以我也给大家:

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        System.out.println("图片配置生效");
        String filePath = System.getProperty("user.dir")+"\\src\\main\\resources\\static\\img\\";
        System.out.println(filePath);
        registry.addResourceHandler("/img/**").addResourceLocations("file:"+filePath);
    }
}

依赖问题
很简答,我没用什么很花里胡哨的操作。如果你是直接复制这个demo的话,只需要加一个thymeleaf就行,配置文件不用谢任何东西。

这个也是缠了我好几天的问题了,我i也终于解决了,啊,爽
Springboot结合前端上传图片保存到数据库读取_第4张图片
最后给一张结构图,仅供参考:
Springboot结合前端上传图片保存到数据库读取_第5张图片
如果对你有帮助,请尽情留下你的评论和点赞,我不会嫌弃的哦。
如果哪儿有值得改进的地方,也请告诉我,我会马上加以改进;

谢谢你这么忙还来看我的文章,靓仔!

你可能感兴趣的:(技术杂谈,java,web,springboot,formdata,filereader)