SSM阶段图片处理相关问题汇总

同步中图片上传至控制器:

JSP页面

<form action="${pageContext.request.contextPath}/file/upLoad" method="post" enctype="multipart/form-data">
    学生姓名:<input type="text" name="stuName"><br>
    学生图像:<input type="file" name="stuImg"><br>
    <input type="submit" value="提交">
</form>

 需要注意:包含图片上传的表单,需要请求方式为post,enctype="multipart/form-data"(必须)

控制器:

    //  进行文件上传的操作
    @RequestMapping("/upLoad")
    public String upLoadTest(String stuName, MultipartFile stuImg, HttpServletRequest request) throws IOException {
        // 获取文件上传的路径 
        // request.getServletContext():获取当前项目的路径
        // getRealPath("/static/upload"):获取当前项目下static/upload的路径
        String dir = request.getServletContext().getRealPath("/static/upload");
        // 判断文件的路径是否存在,不存在则创建
        File path = new File(dir);
        if (!path.exists()) {
            path.mkdirs();
        }
        // 获取文件的原始名称
        String oldFileName = stuImg.getOriginalFilename();
        // 获取文件的新名称
        String newFileName = FileNameByUUID.getFileName() + FileTypeUtil.getFileType(oldFileName);
        // 将文件写入到指定的路径中
        File file = new File(dir, newFileName);
        stuImg.transferTo(file);
        //如果要将图片保存至数据库中,newFileName就是要保存的文件名
        
        //数据库图片字段存图片名称,读取图片时,根据图片名称就可以找到图片
        return "index";
    }

这里使用到的工具类:

FileNameByUUID(给文件起一个不重复的名字)

FileTypeUtil(获取文件的后缀名,例如:.jpg)

为什么要给文件重命名?因为可能出现不同用户上传名字相同内容不同的图片,例两张11.jpg,但两张内容不同,如果不重命名,同名文件会出现后一个文件覆盖上一个文件

用到的工具类

import java.util.UUID;
public class FileNameByUUID {
    private FileNameByUUID() {
    }

    public static String getFileName() {
        String fileName = UUID.randomUUID().toString().replace("-", "");
        return fileName;
    }
}
public class FileTypeUtil {
    private FileTypeUtil() {
    }

    public static String getFileType(String fileName) {
        int index = fileName.lastIndexOf(".");
        String fileType = fileName.substring(index);
        return fileType;
    }
}

扩展:文件下载功能

JSP页面

<body>
<p>头像一</p>
<a href="${pageContext.request.contextPath}/file/downLoad?fileName=头像1.JPG">头像1.JPG</a>
<a href="${pageContext.request.contextPath}/file/download2?fileName=头像1.JPG">头像1.JPG</a>
</body>

控制器

    //  进行文件下载的操作
    @RequestMapping("/downLoad")
    public void downLoad(String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException {
        //设置响应头
        //如果文件名有中文,需要设置为utf-8
        String saveFileName = URLEncoder.encode(fileName, "utf-8");
        //告诉浏览器发送的数据是一个附件,浏览器收到后会自动下载
        response.setHeader("Content-Disposition", "attachment; filename=" + saveFileName);
        //告诉浏览器发送的数据类型
        response.setContentType("application/octet-stream;charset=utf-8"); //二进制流数据(最常见的文件下载)通用数据类型
        //获取文件的真实路径
        String realPath = request.getServletContext().getRealPath("/static/files/" + fileName);
        //将文件内容写入到响应输出流中
        //使用IO流来进行读写操作,读取文件,写入到响应输出流中
        InputStream in = new FileInputStream(realPath);
        //告诉浏览器发送的数据长度
        //获取文件的大小
        int size = in.available();
        //设置响应头的长度:文件的大小
        response.setContentLength(size);
        //获取响应输出流
        ServletOutputStream out = response.getOutputStream();
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = in.read(bys)) != -1) {
            out.write(bys, 0, len);
        }
        out.flush();
        in.close();
        out.close();
    }

    // 实现下载的第二种方式
    @RequestMapping("/download2")
    public ResponseEntity download2(String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException {
        //  得到图片的路径
        String paths = request.getServletContext().getRealPath("/static/files/" + fileName);
        InputStream in = new FileInputStream(paths);
        //定义byte数组,长度就是整个图片的长度
        byte[] bys = new byte[in.available()];
        //读取图片
        in.read(bys);
        //设置响应头
        HttpHeaders headers = new HttpHeaders();
        //封装一个HttpHeader 响应头对象
        //告诉浏览器发送的数据类型
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        //如果文件名有中文,需要设置为utf-8
        String saveFileName = URLEncoder.encode(fileName, "utf-8");
        // 告诉浏览器发送的数据是一个附件,浏览器收到后会自动下载
        headers.setContentDispositionFormData("attachment", saveFileName);
        //告诉浏览器发送的数据长度
        headers.setContentLength(bys.length);
        //将数据,响应头,响应状态码封装到ResponseEntity对象中
        ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bys, headers, HttpStatus.OK);
        // 返回ResponseEntity对象
        return responseEntity;
    }

异步请求实现图片上传至控制器

一般情况下需求是添加:一个表单通过异步请求提交给控制器,目的是把数据保存到数据库中,其中包含图片

情景:添加学生信息,包含学生图像

控制器:(整体思路和同步相同)

    @RequestMapping("/addStudent")
    @ResponseBody
    public ResponseEntity addStudent(Student student, MultipartFile student_img, HttpServletRequest request) throws IOException {
        //MultipartFile student_img 除了图像其余学生信息正常传值,图像单独处理,
        //所以表单上的学生图像字段,不能和实体类字段一致(一致的话就自动映射到studnet对象里面了) 
        //这里实体类是studentImg 表单的name设置为student_img
        // 获取文件夹路径
        String dir = request.getServletContext().getRealPath("/static/image");
        // 判断文件夹是否存在,不存在则创建
        File path = new File(dir);
        if (!path.exists()) {
            path.mkdirs();
        }
        // 获取文件名
        String oldFileName = student_img.getOriginalFilename();
        // 生成新的文件名
        String newFileName = FileNameByUUID.getFileName() + FileTypeUtil.getFileType(oldFileName);
        // 创建文件
        File file = new File(dir, newFileName);
        // 保存文件
        student_img.transferTo(file);
        // 设置图片路径
        student.setStudentImg(newFileName);
        student.setStudentId(IdUtil.getId());
        try {
            Boolean aBoolean = studentService.addStudent(student);
            if (aBoolean) {
                return new ResponseEntity("添加成功", Commons.SUCCESS);
            } else {
                return new ResponseEntity("添加失败", Commons.FAILES);
            }
        } catch (SystemException e) {
            return new ResponseEntity(Commons.EXCEPTIONMSG, Commons.SYSTEMEXCEPTION);
        } catch (BusinessException e) {
            return new ResponseEntity(e.getMessage(), Commons.BUSINESSEXCEPTION);
        } catch (Exception e) {
            return new ResponseEntity("error,请联系管理员", Commons.EXCEPTION);
        }
    }

JSP页面的表单:(引用的是Bootstrap样式)

<!-- Modal -->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close" id="close"><span
                            aria-hidden="true">☣︎</span></button>
                    <h4 class="modal-title" id="myModalLabel">添加学生信息</h4>
                </div>
                <div class="modal-body">
                    <form id="myForm" method="post">
                        学生姓名:<input type="text" name="studentName"><br>
                        学生性别:<input type="radio" name="studentSex" value="男">男 &nbsp;&nbsp;
                        <input type="radio" name="studentSex" value="女">女<br>
                        出生日期:<input type="date" name="studentBornDate"><br>
                        <%--不能和实体类的属性名一样,一样的话就自动装到student对象里面了--%>
                        学生头像:<input type="file" name="student_img" id="showImg">
                        <div id="studentImg">
                            <img src="" id="img" style="width: 50px">
                        </div>
                        <br>
                        学生班级:
                        <select name="studentClass.classId" id="studentClass">
                        </select>
                    </form>

                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
                    <button type="button" class="btn btn-primary" id="btn-save">提交</button>
                </div>
            </div>
        </div>
    </div>

JS代码:

function addStudent() {
    console.log("拿到的数据:" + $("#myForm").serialize());
    $.ajax({
        url: "/springmvc0512_studentByAjax/student/addStudent",
        //type:请求的方式
        type: "post",
        //data:请求的参数
        data: new FormData($("#myForm")[0]),
        //contentType:false
        contentType: false,
        //processData指不对数据做任何处理
        processData: false,
        success: function (msg) {
            if (msg.code == 200) {
                //bootstrap中拟态框写好的关闭样式
                $('#myModal').modal('hide');
                //再刷新一个页面
                loadStudent(1, 4);
                /* $("#close").trigger("click");
                 console.log("确认已经点击")
                 alert("添加成功!");*/
            } else if (msg.code == 500) {
                $('#myModal').modal('hide');
                alert(msg.message);
            } else if (msg.code == 400) {
                $('#myModal').modal('hide');
                alert(msg.message);
            }
        }
    });
}

到此:同步异步在控制器获取图片都已经解决

另外,因为数据库保存的是图片名称,如果需求是删除这条数据也需要把对应的图片删除的话

controller:(以学生信息为例)

    @RequestMapping("/delete")
    public ResponseEntity delete(Integer studentId, HttpServletRequest request) {
        try {
            //根据学生编号查询学生信息
            Student byId = studentService.getById(studentId);
            //获取学生头像
            String studentImg = byId.getStudentImg();
            //删除学生信息 一定要在删除学生头像之前获取图片名称,要不然删了就获取不到了
            Boolean delete = studentService.delete(studentId);
            if (delete) {
                //如果删除操作成功了,对应的把图片也删除
                //获取图片的路径
                String path = request.getServletContext().getRealPath("/static/image/" + studentImg);
                //根据路径创建文件对象
                File file = new File(path);
                //判断文件是否存在,存在则删除
                if (file.exists()) {
                    file.delete();
                }
                return new ResponseEntity(Commons.SUCCESS, "成功!");
            } else {
                return new ResponseEntity(Commons.FAILES, "失败!");
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return new ResponseEntity(Commons.EXCEPTIONMSG, Commons.EXCEPTION);
        }
    }

更新操作,是通过主键更新所有字段,因为其他的标签都可以写默认值,但是图片不能写默认值

那么,如果用户没有对图片进行修改的话,空图片进入控制器后进入数据库,用户原本的图片就没有了

解决思路:

1、使用动态SQL判断图片字段是否为空,为空则不修改

2、在控制器判断用户是否修改了图片,如果没有修改,查出来用户之前的图片并赋值给对象,然后再进行更新

方法2代码示例:

    @RequestMapping("/update/{studentId}")
    public ResponseEntity update(Student student, @PathVariable("studentId") Integer studentId, MultipartFile stuImg, HttpServletRequest request) {
        try {
            student.setStudentId(studentId);
            Boolean updateMsg = false;
            String oldStudentImg = null;
            if (stuImg != null) {//如果用户修改了图片
                //查询用户之前的图片,修改完成后把之前的图片删除
                Student byId = studentService.getById(studentId);
                oldStudentImg = byId.getStudentImg();
                String dir = request.getServletContext().getRealPath("/static/image");
                // 判断文件夹是否存在,不存在则创建
                File path = new File(dir);
                if (!path.exists()) {
                    path.mkdirs();
                }
                String oldFileName = stuImg.getOriginalFilename();
                String newFileName = FileNameByUUID.getFileName() + FileTypeUtil.getFileType(oldFileName);
                File file = new File(dir, newFileName);
                stuImg.transferTo(file);
                student.setStudentImg(newFileName);
                updateMsg = studentService.update(student);
            } else {
                Student byId = studentService.getById(student.getStudentId());
                student.setStudentImg(byId.getStudentImg());
                updateMsg = studentService.update(student);
            }
            if (updateMsg) {
                if (oldStudentImg != null) {
                    //如果修改成功了,对应的把图片也删除
                    //获取图片的路径
                    String path = request.getServletContext().getRealPath("/static/image/" + oldStudentImg);
                    //根据路径创建文件对象
                    File file = new File(path);
                    //判断文件是否存在,存在则删除
                    if (file.exists()) {
                        file.delete();
                    }
                }
                return new ResponseEntity(Commons.SUCCESS, "成功!");
            } else {
                return new ResponseEntity(Commons.FAILES, "失败!");
            }
        } catch (IOException e) {
            System.out.println(e.getMessage());
            return new ResponseEntity(Commons.EXCEPTIONMSG, Commons.EXCEPTION);
        }
    }

扩展:如何实现这种效果

 

 JSP

学生头像:<input type="file" name="student_img" id="showImg">
                        <div id="studentImg">
                            <img src="" id="img" style="width: 50px">
                        </div>

JS

<script>
    window.onload = function () {
        //获取下拉框
        let input_file = document.querySelector("#showImg");
        //给下拉框添加事件
        input_file.onchange = function () {
            //判断是否有文件
            if (input_file.files.length > 0) {
                //获取文件
                let file = input_file.files[0];
                //创建文件读取对象
                let reader = new FileReader();
                //读取文件
                reader.readAsDataURL(file);
                //读取完成后
                reader.onload = function () {
                    //获取img标签
                    let img = document.querySelector("#img");
                    //设置img标签的src属性
                    img.src = reader.result;
                }
            }
        }
    }
</script>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值