• JavaWeb图片上传的几种方式


    一、图片上传介绍

    JavaWeb方向编程过程中,实现图片上传有三种方式:

    1、传统的基于springMVC的MultipartFile类实现图片上传。

    2、基于Ajax的图片上传。

    3、基于Base64压缩的图片上传。

    二、springMVC图片上传(springboot通用)

    此方法的优点是可以将图片和其他的表单元素一起提交到服务器,服务器接受到的图片其实已经存储于容器的临时文件中,进行文件拷贝工作比较简单。

    缺点是无法及时看到图片上传的预览效果,图片一旦选择错误只能重新提交。

    注:红色代码为关键代码。

    1、页面代码

    <form action="/upload" method="post" enctype="multipart/form-data">
        选择头像:<input type="file" name="file" accept="image/*" /> <br>
        用户名字:<input type="text" name="userName"/> <br>
        <input type="submit" value="提交">
    </form>

    2、config.properties配置文件

    创建名为config.properties的配置文件,并且再其中配置图片上传物理路径。注意window和linux的写法不同。

    **此配置内容在springboot结构中的application.properties文件中配置**

    file.location.path=d:/upload

    3、spring-servlet.xml配置文件 

    **此配置文件在springboot中不需要配置 - “习惯大于配置”**

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
        <!-- 设置使用注解的类所在的jar包 -->
        <context:component-scan base-package="org.lanqiao.service"/>
        <context:component-scan base-package="org.lanqiao.controller"/>
        <!--读取属性文件-->
        <context:property-placeholder location="classpath:config.properties" ignore-unresolvable="true"/>
        <!-- 注册HandlerMapping和HandlerAdapter组件 -->
        <mvc:annotation-driven/>
        <!-- 对静态资源文件的访问 支持访问WEB-INF目录 -->
        <mvc:default-servlet-handler/>
        <!-- 对转向页面的路径解析。prefix:前缀,suffix:后缀 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
                p:prefix="/" p:suffix=".jsp"/>
        <!--文件上传-->
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="maxUploadSize" value="104857600"/>
            <property name="maxInMemorySize" value="4096"/>
            <property name="defaultEncoding" value="UTF-8"/>
        </bean>
    </beans>

    4、controller代码

    若是一次上传多个文件,需要使用注解@RequestParam("inputName") 指明该文件对应表单中的input标签的name属性。如果name都是同名的,可以使用MultipartFile [] 文件数组来接收

    @Controller
    public class UserController {
        @Autowired
        UserService userService;
        @Value("${file.location.path}")
        private String fileLocation;
        @RequestMapping("/insert")
        public String insert(User user, MultipartFile file){
            String uri = FileUpload.upload(file,"/upload",fileLocation);
            user.setFacePic(uri);
            int ret = userService.insertUser(user);
            if(ret > 0 ){
                return "redirect:/get";
            }else{
                return "register";
            }
        }
    }

    5、上传工具类代码

    public class FileUpload {
        /**
         * @param file 上传的文件
         * @param path 文件的虚拟路径,例如 /upload
         * @param fileLocation 文件的物理路径,例如d:/upload
         * @return 文件的虚拟路径+文件名
         *
         * fileName.lastIndexOf(".")为获取后缀名
         * UUID.randomUUID()为获取唯一标识,保证文件的唯一性
         */
        public static String upload(MultipartFile file, String path, String fileLocation) {
            String fileFinishName = null;
            try {
                // 如果目录不存在则创建
                File uploadDir = new File(fileLocation);
                if (!uploadDir.exists()) {
                    uploadDir.mkdir();
                }
                //获取源文件名称
                String fileName = file.getOriginalFilename();
                fileFinishName = UUID.randomUUID() + fileName.substring(fileName.lastIndexOf("."), fileName.length());
                //上传文件到指定目录下
                File uploadFile = new File(uploadDir + uploadDir.separator + fileFinishName);
                file.transferTo(uploadFile);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return path + "/" + fileFinishName;
        }
    }

    三、基于Ajax的图片上传

    这种方式同第一种方式一样都是使用multipart/form-data方式上传,服务器端同样使用springMVC(springboot)实现所以只有页面代码不一致,其他代码(2、3、4、5)同上。

    该方式前端使用的是jQuery的jquery.fileupload.js插件来实现。详见大神文章:https://blog.csdn.net/qq_37936542/article/details/79258158

    1、页面先一用jQuery的插件

    下载地址:https://github.com/blueimp/jQuery-File-Upload

    **顺序不能错误**

    <script src="js/jquery-3.2.1.min.js"></script>
    <!-- jquery file upload相关js -->
    <script src="js/jquery.ui.widget.js"></script>
    <script src="js/jquery.iframe-transport.js"></script>
    <script src="js/jquery.fileupload.js"></script>
    <script src="js/jquery.fileupload-process.js"></script>
    <script src="js/jquery.fileupload-validate.js"></script>

    2、HTML代码编写

    **不需要form标签**

    <style>
    /* input样式 */
    #uploadImg{
    display: none;
    }
     
    /* button样式 */
    #chooseFile{
    background: #93b6fc;
    }
     
    #uploadFile,#rechooseFile {
    display: none;
    background: #93b6fc;
    }
     
    #image{
      200px;
      height:200px;
    }
     
    /* 进度条样式 */
    .bar { 
     background-image: -webkit-linear-gradient(top,#5cb85c 0,#449d44 100%); 
     background-image: -o-linear-gradient(top,#5cb85c 0,#449d44 100%); 
     background-image: -webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44)); 
     background-image: linear-gradient(to bottom,#5cb85c 0,#449d44 100%); 
     filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 
     background-repeat: repeat-x; 
     height: 20px; 
     line-height: 20px; 
     -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.15); 
     box-shadow: inset 0 -1px 0 rgba(0,0,0,.15); 
     -webkit-transition: width .6s ease; 
     -o-transition: width .6s ease; 
     transition: width .6s ease; 
    }
    #progress { 
     filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 
     background-repeat: repeat-x; 
     height: 20px; 
      0%; 
     margin-bottom: 20px; 
     overflow: hidden; 
     background-color: #f5f5f5; 
     border-radius: 4px; 
     -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 
     box-shadow: inset 0 1px 2px rgba(0,0,0,.1); 
     margin-top: 20px; 
    }
    </style>
    <body>
        <div class="jquery-fileupload">
            <div class="">
                <input id="uploadImg" type="file" name="uploadImg" multiple style="display: none" /> 
                    <button id="chooseFile">+选择文件</button> 
                    <button id="uploadFile">~开始上传</button>
                    <button id="rechooseFile">+重新选择</button>
            </div>
            <div>
                <img id="image" src="">
            </div>
            <div id="progress">
                <div class="bar" style=" 0%;"></div>
            </div>
        </div>
    </body>

    3、js代码

    $(function() {
            $("#chooseFile").on("click", function() {
                $("#uploadImg").click();
            });
     
            $('#uploadImg').fileupload({
                url : '/upload',//请求发送的目标地址
                Type : 'POST',//请求方式 ,可以选择POST,PUT或者PATCH,默认POST
                //dataType : 'json',//服务器返回的数据类型
                autoUpload : false,
                acceptFileTypes : /(gif|jpe?g|png)$/i,//验证图片格式
                maxNumberOfFiles : 1,//最大上传文件数目
                maxFileSize : 1000000, // 文件上限1MB
                minFileSize : 100,//文件下限  100b
                messages : {//文件错误信息
                    acceptFileTypes : '文件类型不匹配',
                    maxFileSize : '文件过大',
                    minFileSize : '文件过小'
                }
            })
            //图片添加完成后触发的事件
            .on("fileuploadadd", function(e, data) {
                //validate(data.files[0])这里也可以手动来验证文件格式和大小
                
                //隐藏或显示页面元素
                $('#progress .bar').css( 
                    'width', '0%'
                  );
                $('#progress').hide();
                $("#chooseFile").hide();
                $("#uploadFile").show();
                $("#rechooseFile").show();
                
                //获取图片路径并显示
                var url = getUrl(data.files[0]);
                $("#image").attr("src", url);
                
                //绑定开始上传事件
                $('#uploadFile').click(function() {
                    $("#uploadFile").hide();
                    jqXHR = data.submit();
                    //解绑,防止重复执行
                    $("#uploadFile").off("click"); 
                })
                
                //绑定点击重选事件
                $("#rechooseFile").click(function(){
                    $("#uploadImg").click();
                    //解绑,防止重复执行
                    $("#rechooseFile").off("click"); 
                })
            })
            //当一个单独的文件处理队列结束触发(验证文件格式和大小)
            .on("fileuploadprocessalways", function(e, data) {
                //获取文件
                file = data.files[0];
                //获取错误信息
                if (file.error) {
                    console.log(file.error);
                    $("#uploadFile").hide();
                }
            })
            //显示上传进度条
            .on("fileuploadprogressall", function(e, data) {
                $('#progress').show();
                 var progress = parseInt(data.loaded / data.total * 100, 10); 
                  $('#progress').css( 
                   'width','15%'
                  ); 
                  $('#progress .bar').css( 
                   'width',progress + '%'
                  ); 
            })
            //上传请求失败时触发的回调函数
            .on("fileuploadfail", function(e, data) {
                console.log(data.errorThrown);
            })
            //上传请求成功时触发的回调函数
            .on("fileuploaddone", function(e, data) {
                alert(data.result);
                
            })
            //上传请求结束后,不管成功,错误或者中止都会被触发
            .on("fileuploadalways", function(e, data) {
     
            })
     
            
            //手动验证
            function validate(file) {
                //获取文件名称
                var fileName = file.name;
                //验证图片格式
                if (!/.(gif|jpg|jpeg|png|gif|jpg|png)$/.test(fileName)) {
                    console.log("文件格式不正确");
                    return true;
                }
                //验证excell表格式
                /*  if(!/.(xls|xlsx)$/.test(fileName)){
                     alert("文件格式不正确");
                     return true;
                 } */
     
                //获取文件大小
                var fileSize = file.size;
                if (fileSize > 1024 * 1024) {
                    alert("文件不得大于一兆")
                    return true;
                }
                return false;
            }
     
            //获取图片地址
            function getUrl(file) {
                var url = null;
                if (window.createObjectURL != undefined) {
                    url = window.createObjectURL(file);
                } else if (window.URL != undefined) {
                    url = window.URL.createObjectURL(file);
                } else if (window.webkitURL != undefined) {
                    url = window.webkitURL.createObjectURL(file);
                }
                return url;
            }
     
        });

     四、基于Base64压缩的图片上传

    图片的Base64 编码就是可以将一副图片数据编码成一串字符串,使用该字符串代替图像地址。例如:

    基于Base64实现图片上传其实就是在浏览器端先将图片转换成字符串,然后将代表图片的字符串传输到服务器进行存储。需要显示的时候可以将字符串写入<img src="">直接显示。

    该图片上传的方式比较简单,且没有其他的例如跨域提交、头文件等问题。但是其编码后的字符串大小远远大于实际的图片大小。所以只适合上传小尺寸的图片,例如用户头像等。

    1、页面代码

    $("#img").change(function (e) {
            var img = e.target.files[0];
            var reader = new FileReader();
            reader.readAsDataURL(img);
            reader.onload = function (e) {
            // ajax 上传图片
              $.post("uploadPic", {img: e.target.result}, function (ret) {
                 if (ret.img != '') {
                    //显示图片
                    $('#showimg').attr("src", ret.imgUrl);
                 }
              }, 'json');
        } });

    2、服务器接收到Base64字符串,就可以得到图片并且将图片直接存入数据库。这里不再描述。

     五、配置图片访问路径

    1、Springboot中可以使用下面的代码将虚拟路径/image/**下的图片映射成到D://盘下。

    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
    
    /**
     * 图片绝对地址与虚拟地址映射
     * 访问地址示例:http://localhost:8080/image/1.png
     */
    
    @Configuration
    public class WebMvcConfig extends WebMvcConfigurationSupport {
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            //windows
            //registry.addResourceHandler("/image/**").addResourceLocations("file:d://upload/");
            //linux和mac
            registry.addResourceHandler("/image/**").addResourceLocations("file:/Users/David/upload/");
            registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        }
    
    }

     2、如果使用springMVC的SSM框架,则可以在tomcat的service.xml文件中直接配置虚拟路径,代码如下:

    <Context docBase="/Users/David/upload" path="/image" reloadable="true"/>

    参考资料:

    https://www.imooc.com/article/27804

  • 相关阅读:
    (13)使用Ajax Helper 提高用户体验
    (12)改变图片的大小生成缩略图
    (11)通过表单上传文件
    程序员需要有多懒 ?- cocos2d-x 数学函数、常用宏粗整理
    xCode 4.X 免证书真机发布及调试
    35岁前必须做好的10件事情(转载)
    独自收集Cocos2d提供的字体!共57种(有对照的字体图)
    (10)根据关键字搜索
    tcp拥塞控制
    dpcnv reademe
  • 原文地址:https://www.cnblogs.com/david1216/p/11515246.html
Copyright © 2020-2023  润新知