SpringMVC(十一):SpringMVC文件上传中要解决的问题

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

    文章目录

    SpringMVC文件上传中要解决的问题

    一、中文文件名编码问题

    二、文件位置存储问题

    三、文件名冲突问题

    四、控制文件类型和大小 

    五、上传图片回显问题

    六、进度条问题

    七、单独准备文件存储服务器

    八、保存完整player信息进入数据库


    SpringMVC文件上传中要解决的问题

    一、中文文件名编码问题

    通过过滤器解决

    二、文件位置存储问题

    放在当前项目下作为静态资源这样可以通过URL访问。

    package com.lanson.controller;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.multipart.MultipartFile;
    import javax.servlet.http.HttpServletRequest;
    import java.io.File;
    import java.io.IOException;
    /**
     * @Author: Lansonli
     * @Description: MircoMessage:Mark_7001
     */
    @Controller
    public class FileUploadController {
        @ResponseBody
        @RequestMapping("fileUpload.do")
        public String fileUpload(MultipartFile headPhoto, HttpServletRequest req) throws IOException {
            // 指定文件存储目录为我们项目部署环境下的upload目录
            String realPath = req.getServletContext().getRealPath("/upload");
            File dir = new File(realPath);
            // 如果不存在则创建目录
            if(!dir.exists()){
                dir.mkdirs();
            }
            // 获取文件名
            String originalFilename = headPhoto.getOriginalFilename();
            // 文件存储位置
            File file =new File(dir,originalFilename);
            //  文件保存
            headPhoto.transferTo(file);
            return "OK";
        }
    }

    在SpringMVC中配置静态资源放行

    <mvc:resources mapping="/upload/**" location="/upload/"></mvc:resources>

     

    三、文件名冲突问题

    使用UUID对文件名进行重命名。

     

    package com.lanson.controller;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.multipart.MultipartFile;
    import javax.servlet.http.HttpServletRequest;
    import java.io.File;
    import java.io.IOException;
    import java.util.UUID;
    /**
     * @Author: Lansonli
     * @Description: MircoMessage:Mark_7001
     */
    @Controller
    public class FileUploadController {
        @ResponseBody
        @RequestMapping("fileUpload.do")
        public String fileUpload(MultipartFile headPhoto, HttpServletRequest req) throws IOException {
            // 指定文件存储目录为我们项目部署环境下的upload目录
            String realPath = req.getServletContext().getRealPath("/upload");
            File dir = new File(realPath);
            // 如果不存在则创建目录
            if(!dir.exists()){
                dir.mkdirs();
            }
            // 获取文件名
            String originalFilename = headPhoto.getOriginalFilename();
            // 避免文件名冲突,使用UUID替换文件名
            String uuid = UUID.randomUUID().toString();
            // 获取拓展名
            String extendsName = originalFilename.substring(originalFilename.lastIndexOf("."));
            // 新的文件名
            String newFileName=uuid.concat(extendsName);
            // 文件存储位置
            File file =new File(dir,newFileName);
            //  文件保存
            headPhoto.transferTo(file);
            return "OK";
        }
    }

    四、控制文件类型和大小 

    package com.lanson.controller;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.multipart.MultipartFile;
    import javax.servlet.http.HttpServletRequest;
    import java.io.File;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    /**
     * @Author: Lansonli
     * @Description: MircoMessage:Mark_7001
     */
    @Controller
    public class FileUploadController {
        @ResponseBody
        @RequestMapping("fileUpload.do")
        public Map<String,String> fileUpload(MultipartFile headPhoto, HttpServletRequest req) throws IOException {
            Map<String,String> map=new HashMap<>();
            // 控制文件大小
            if(headPhoto.getSize()>1024*1024*5){
                map.put("message", "文件大小不能超过5M");
                return map;
            }
            // 指定文件存储目录为我们项目部署环境下的upload目录
            String realPath = req.getServletContext().getRealPath("/upload");
            File dir = new File(realPath);
            // 如果不存在则创建目录
            if(!dir.exists()){
                dir.mkdirs();
            }
            // 获取文件名
            String originalFilename = headPhoto.getOriginalFilename();
            // 避免文件名冲突,使用UUID替换文件名
            String uuid = UUID.randomUUID().toString();
            // 获取拓展名
            String extendsName = originalFilename.substring(originalFilename.lastIndexOf("."));
            //  控制文件类型
            if(!extendsName.equals(".jpg")){
                map.put("message", "文件类型必须是.jpg");
                return map;
            }
            // 新的文件名
            String newFileName=uuid.concat(extendsName);
            // 文件存储位置
            File file =new File(dir,newFileName);
            //  文件保存
            headPhoto.transferTo(file);
            // 上传成功之后,把文件的名字和文件的类型返回给浏览器
            map.put("message", "上传成功");
            map.put("newFileName", newFileName);
            map.put("filetype", headPhoto.getContentType());
            return map;
        }
    }
    

    通过文件上传解析组件控制。

    但是会出现异常后期可以可以配置一个异常解析器解决。

    <!--文件上传解析组件
        id必须为multipartResolver
        springmvc默认使用该id找该组件
        -->
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <!--设置文件大小-->
            <property name="maxUploadSizePerFile" value="10"></property>
        </bean>

    五、上传图片回显问题

    后天已经将图片的文件名响应给浏览器。

    前端代码

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
        <script type="text/javascript" src="js/jquery.min.js"></script>
        <script type="text/javascript">
            $(function(){
                $("#uploadFile").click(function(){
                    // 获取要上传的文件
                    var photoFile =$("#photo")[0].files[0]
                    if(photoFile==undefined){
                        alert("您还未选中文件")
                        return;
                    }
                    // 将文件装入FormData对象
                    var formData =new FormData();
                    formData.append("headPhoto",photoFile)
                    // ajax向后台发送文件
                    $.ajax({
                        type:"post",
                        data:formData,
                        url:"fileUpload.do",
                        processData:false,
                        contentType:false,
                        success:function(result){
                            // 接收后台响应的信息
                            alert(result.message)
                            // 图片回显
                            $("#headImg").attr("src","upload/"+result.newFileName);
                        }
                    })
                })
            })
        </script>
    </head>
    <body>
        <form action="addPlayer" method="get">
            <p>账号<input type="text" name="name"></p>
            <p>密码<input type="text" name="password"></p>
            <p>昵称<input type="text" name="nickname"></p>
            <p>头像:
                <br/>
                <input id="photo" type="file">
                <br/>
                <img id="headImg" style="width: 200px;height: 200px" alt="你还未上传图片">
                <br/>
                <a id="uploadFile" href="javascript:void(0)">立即上传</a>
            </p>
            <p><input type="submit" value="注册"></p>
        </form>
    </body>
    </html>

    六、进度条问题

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
        <style>
            .progress {
                width: 200px;
                height: 10px;
                border: 1px solid #ccc;
                border-radius: 10px;
                margin: 10px 0px;
                overflow: hidden;
            }
            /* 初始状态设置进度条宽度为0px */
            .progress > div {
                width: 0px;
                height: 100%;
                background-color: yellowgreen;
                transition: all .3s ease;
            }
        </style>
        <script type="text/javascript" src="js/jquery.min.js"></script>
        <script type="text/javascript">
            $(function(){
                $("#uploadFile").click(function(){
                    // 获取要上传的文件
                    var photoFile =$("#photo")[0].files[0]
                    if(photoFile==undefined){
                        alert("您还未选中文件")
                        return;
                    }
                    // 将文件装入FormData对象
                    var formData =new FormData();
                    formData.append("headPhoto",photoFile)
                    // ajax向后台发送文件
                    $.ajax({
                        type:"post",
                        data:formData,
                        url:"fileUpload.do",
                        processData:false,
                        contentType:false,
                        success:function(result){
                            // 接收后台响应的信息
                            alert(result.message)
                            // 图片回显
                            $("#headImg").attr("src","upload/"+result.newFileName);
                        },
                        xhr: function() {
                            var xhr = new XMLHttpRequest();
                            //使用XMLHttpRequest.upload监听上传过程注册progress事件打印回调函数中的event事件
                            xhr.upload.addEventListener('progress', function (e) {
                                //loaded代表上传了多少
                                //total代表总数为多少
                                var progressRate = (e.loaded / e.total) * 100 + '%';
                                //通过设置进度条的宽度达到效果
                                $('.progress > div').css('width', progressRate);
                            })
                            return xhr;
                        }
                    })
                })
            })
        </script>
    </head>
    <body>
        <form action="addPlayer" method="get">
            <p>账号<input type="text" name="name"></p>
            <p>密码<input type="text" name="password"></p>
            <p>昵称<input type="text" name="nickname"></p>
            <p>头像:
                <br/>
                <input id="photo" type="file">
                <%--图片回显--%>
                <br/>
                <img id="headImg" style="width: 200px;height: 200px" alt="你还未上传图片">
                <br/>
               <%--进度条--%>
                <div class="progress">
                    <div></div>
                </div>
                <a id="uploadFile" href="javascript:void(0)">立即上传</a>
            </p>
            <p><input type="submit" value="注册"></p>
        </form>
    </body>
    </html>
    

    七、单独准备文件存储服务器

    分服务器上传作用

    • 数据库服务器运行我们的数据库
    • 缓存和消息服务器负责处理大并发访问的缓存和消息
    • 文件服务器负责存储用户上传文件的服务器。
    • 应用服务器负责部署我们的应用

    在实际开发中我们会有很多处理不同功能的服务器。注意此处说的不是服务器集群

    总结分服务器处理的目的是让服务器各司其职从而提高我们项目的运行效率。

    分服务器工作示意图

     

    单独解压一个Tomcat作为文件服务器

    设置远程服务器端口号 

     

    远程服务器中设置非只读

     

    webapps下创建一个upload目录

     

    启动测试

    项目中导入依赖

    <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
      <version>1.19</version>
    </dependency>

    controller代码

    package com.lanson.controller;
    import com.sun.jersey.api.client.Client;
    import com.sun.jersey.api.client.WebResource;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.multipart.MultipartFile;
    import javax.servlet.http.HttpServletRequest;
    import java.io.File;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    /**
     * @Author: Lansonli
     * @Description: MircoMessage:Mark_7001
     */
    @Controller
    public class FileUploadController {
        // 文件存储位置
        private final static String FILESERVER="http://192.168.8.109:8090/upload/";
        @ResponseBody
        @RequestMapping("fileUpload.do")
        public Map<String,String> fileUpload(MultipartFile headPhoto, HttpServletRequest req) throws IOException {
            Map<String,String> map=new HashMap<>();
            // 获取文件名
            String originalFilename = headPhoto.getOriginalFilename();
            // 避免文件名冲突,使用UUID替换文件名
            String uuid = UUID.randomUUID().toString();
            // 获取拓展名
            String extendsName = originalFilename.substring(originalFilename.lastIndexOf("."));
            // 新的文件名
            String newFileName=uuid.concat(extendsName);
            // 创建 sun公司提供的jersey包中的client对象
            Client client=Client.create();
            WebResource resource = client.resource(FILESERVER + newFileName);
            //  文件保存到另一个服务器上去了
            resource.put(String.class, headPhoto.getBytes());
            // 上传成功之后,把文件的名字和文件的类型返回给浏览器
            map.put("message", "上传成功");
            map.put("newFileName",newFileName);
            map.put("filetype", headPhoto.getContentType());
            return map;
        }
    }
    

    页面代码

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
        <style>
            .progress {
                width: 200px;
                height: 10px;
                border: 1px solid #ccc;
                border-radius: 10px;
                margin: 10px 0px;
                overflow: hidden;
            }
            /* 初始状态设置进度条宽度为0px */
            .progress > div {
                width: 0px;
                height: 100%;
                background-color: yellowgreen;
                transition: all .3s ease;
            }
        </style>
        <script type="text/javascript" src="js/jquery.min.js"></script>
        <script type="text/javascript">
            $(function(){
                $("#uploadFile").click(function(){
                    // 获取要上传的文件
                    var photoFile =$("#photo")[0].files[0]
                    if(photoFile==undefined){
                        alert("您还未选中文件")
                        return;
                    }
                    // 将文件装入FormData对象
                    var formData =new FormData();
                    formData.append("headPhoto",photoFile)
                    // ajax向后台发送文件
                    $.ajax({
                        type:"post",
                        data:formData,
                        url:"fileUpload.do",
                        processData:false,
                        contentType:false,
                        success:function(result){
                            // 接收后台响应的信息
                            alert(result.message)
                            // 图片回显
                            $("#headImg").attr("src","http://192.168.8.109:8090/upload/"+result.newFileName);
                          
                        },
                        xhr: function() {
                            var xhr = new XMLHttpRequest();
                            //使用XMLHttpRequest.upload监听上传过程注册progress事件打印回调函数中的event事件
                            xhr.upload.addEventListener('progress', function (e) {
                                //loaded代表上传了多少
                                //total代表总数为多少
                                var progressRate = (e.loaded / e.total) * 100 + '%';
                                //通过设置进度条的宽度达到效果
                                $('.progress > div').css('width', progressRate);
                            })
                            return xhr;
                        }
                    })
                })
            })
        </script>
    </head>
    <body>
        <form action="addPlayer" method="get">
            <p>账号<input type="text" name="name"></p>
            <p>密码<input type="text" name="password"></p>
            <p>昵称<input type="text" name="nickname"></p>
            <p>头像:
                <br/>
                <input id="photo" type="file">
                <%--图片回显--%>
                <br/>
                <img id="headImg" style="width: 200px;height: 200px" alt="你还未上传图片">
                <br/>
               <%--进度条--%>
                <div class="progress">
                    <div></div>
                </div>
                <a id="uploadFile" href="javascript:void(0)">立即上传</a>
                
            </p>
            <p><input type="submit" value="注册"></p>
        </form>
    </body>
    </html>

    八、保存完整player信息进入数据库

    index.html

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
        <style>
            .progress {
                width: 200px;
                height: 10px;
                border: 1px solid #ccc;
                border-radius: 10px;
                margin: 10px 0px;
                overflow: hidden;
            }
            /* 初始状态设置进度条宽度为0px */
            .progress > div {
                width: 0px;
                height: 100%;
                background-color: yellowgreen;
                transition: all .3s ease;
            }
        </style>
        <script type="text/javascript" src="js/jquery.min.js"></script>
        <script type="text/javascript">
            $(function(){
                $("#uploadFile").click(function(){
                    // 获取要上传的文件
                    var photoFile =$("#photo")[0].files[0]
                    if(photoFile==undefined){
                        alert("您还未选中文件")
                        return;
                    }
                    // 将文件装入FormData对象
                    var formData =new FormData();
                    formData.append("headPhoto",photoFile)
                    // ajax向后台发送文件
                    $.ajax({
                        type:"post",
                        data:formData,
                        url:"fileUpload.do",
                        processData:false,
                        contentType:false,
                        success:function(result){
                            // 接收后台响应的信息
                            alert(result.message)
                            // 图片回显
                            $("#headImg").attr("src","http://192.168.8.109:8090/upload/"+result.newFileName);
                            // 将文件类型和文件名放入form表单
                            $("#photoInput").val(result.newFileName)
                            $("#filetypeInput").val(result.filetype)
                        },
                        xhr: function() {
                            var xhr = new XMLHttpRequest();
                            //使用XMLHttpRequest.upload监听上传过程注册progress事件打印回调函数中的event事件
                            xhr.upload.addEventListener('progress', function (e) {
                                //loaded代表上传了多少
                                //total代表总数为多少
                                var progressRate = (e.loaded / e.total) * 100 + '%';
                                //通过设置进度条的宽度达到效果
                                $('.progress > div').css('width', progressRate);
                            })
                            return xhr;
                        }
                    })
                })
            })
        </script>
    </head>
    <body>
        <form action="addPlayer" method="get">
            <p>账号<input type="text" name="name"></p>
            <p>密码<input type="text" name="password"></p>
            <p>昵称<input type="text" name="nickname"></p>
            <p>头像:
                <br/>
                <input id="photo" type="file">
                <%--图片回显--%>
                <br/>
                <img id="headImg" style="width: 200px;height: 200px" alt="你还未上传图片">
                <br/>
               <%--进度条--%>
                <div class="progress">
                    <div></div>
                </div>
                <a id="uploadFile" href="javascript:void(0)">立即上传</a>
                <%--使用隐藏的输入框存储文件名称和文件类型--%>
                <input id="photoInput"  type="hidden" name="photo" >
                <input id="filetypeInput"  type="hidden" name="filetype">
            </p>
            <p><input type="submit" value="注册"></p>
        </form>
    </body>
    </html>
    

    FileUploadController代码

    见上一步

    playerController代码

    package com.lanson.controller;
    import com.lanson.pojo.Player;
    import com.lanson.service.PlayerService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    /**
     * @Author: Lansonli
     * @Description: MircoMessage:Mark_7001
     */
    @Controller
    public class PlayerController  {
        @Autowired
        private PlayerService playerService;
        @RequestMapping("addPlayer")
        public String addPlayer(Player player){
            // 调用服务层方法,将数据保存进入数据库
            playerService.addPlayer(player);
            // 页面跳转至player信息展示页
            return "redirect:/showPlayer.jsp";
        }
    }

    Service层代码

    package com.lanson.service.impl;
    import com.lanson.mapper.PlayerMapper;
    import com.lanson.pojo.Player;
    import com.lanson.service.PlayerService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    /**
     * @Author: Lansonli
     * @Description: MircoMessage:Mark_7001
     */
    @Service
    public class PlayerServiceImpl implements PlayerService {
        @Autowired
        private PlayerMapper playerMapper;
        @Override
        public boolean addPlayer(Player player) {
            return playerMapper.addPlayer(player)>0;
        }
    }

    mapper代码

    <?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.lanson.mapper.PlayerMapper">
        <insert id="addPlayer">
            insert into player values(DEFAULT ,#{name},#{password},#{nickname},#{photo},#{filetype})
        </insert>
    </mapper>

    • 📢博客主页https://lansonli.blog.csdn.net
    • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正
    • 📢本文由 Lansonli 原创首发于 CSDN博客🙉
    • 📢停下休息的时候不要忘了别人还在奔跑希望大家抓紧时间学习全力奔赴更美好的生活✨
  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
    标签: Spring