• 前后端分离跨服务器文件上传-Java SpringMVC版


     近来工作上不上特别忙,加上对后台java了解一点,所以就抽时间,写了一个java版本的前后端分离的跨服务器文件上传功能,包括前后端代码。

     需要购买阿里云产品和服务的,点击此链接领取优惠券红包,优惠购买哦,领取后一个月内有效: https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=fp9ccf07

    一、Tomcat服务器部分

    1、Tomcat服务器

    单独复制一份Tomcat,用来作为文件服务器

    1.1 web.xml文件:

    需要在该Tomcat的conf目录下的web.xml文件的大概100行添加如下几行(红框内部分):

    1.2 server.xml文件:

    需要在该Tomcat的conf目录下的server.xml文件做一些端口的修改

    1.3 Tomcat下建立文件夹

    在该Tomcat的/webapps/ROOT目录下创建一个upload目录,用来存放上传的文件

    1.4 启动Tomcat服务器

    以上三步做完后,就可以启动Tomcat服务器了,在Tomcat的bin目录下执行 startup.sh 脚本

    二、java部分

    2.1 jar包

    除了其他的jar包以外,还需要以下几个jar包

    commons-io-1.3.2.jar

    commons-fileupload-1.2.1.jar

    jersey-client-1.18.1.jar

    jersey-core-1.18.1.jar

    jersey-common

    2.2 配置文件

    2.2.1 spring-mvc.xml文件添加如下部分:

    <!-- 上传文件 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
      <!--最大上传尺寸  5M -->
       <property name="maxUploadSize" value="5242880"/>
    </bean>

    2.2.2 config.properties 文件添加如下部分:

    #文件服务器地址
    uploadHost=http://172.16.5.102:8090/
    #上传的文件保存的目录 imgPath = upload/

    2.3 java文件

    2.3.1 Upload.java

    package com.lin.utils;
    
    import java.io.File;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.io.FilenameUtils;
    import org.springframework.web.multipart.MultipartFile;
    
    import com.sun.jersey.api.client.Client;
    import com.sun.jersey.api.client.WebResource;
    
    
    /**
     * 上传文件工具类
     * @author libo
     */
    public class Upload {
        
        /**
         * 上传文件
         * @param request
         * @param response
         * @param serverPath    服务器地址:(http://172.16.5.102:8090/)
         * @param path             文件路径(不包含服务器地址:upload/)
         * @return
         */
        public static String upload(Client client, MultipartFile file, HttpServletRequest request,HttpServletResponse response, String serverPath, String path){
            // 文件名称生成策略(UUID uuid = UUID.randomUUID())
            Date d = new Date();
            SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
            String formatDate = format.format(d);
            String str = "";
            for(int i=0 ;i <5; i++){
                int n = (int)(Math.random()*90)+10;
                str += n;
            }
            // 获取文件的扩展名
            String extension = FilenameUtils.getExtension(file.getOriginalFilename());
            // 文件名
            String fileName = formatDate + str + "." + extension;
            //相对路径
            String relaPath = path + fileName;
            
            String a = serverPath + path.substring(0, path.lastIndexOf("/"));
            File file2 = new File(a);
            if(!file2.exists()){
                boolean mkdirs = file2.mkdirs();
                System.out.println(mkdirs);
            }
            
            // 另一台tomcat的URL(真实路径)
            String realPath = serverPath + relaPath;
            // 设置请求路径
            WebResource resource = client.resource(realPath);
    
            // 发送开始post get put(基于put提交)
            try {
                resource.put(String.class, file.getBytes());
                return fileName+";"+relaPath+";"+realPath;
            } catch (IOException e) {
                e.printStackTrace();
                return "";
            }
        }
        
        /**
         * 删除文件
         * @param filePath(文件完整地址:http://172.16.5.102:8090/upload/1234.jpg)
         * @return
         */
        public static String delete(String filePath){
            try {
                Client client = new Client();
                WebResource resource = client.resource(filePath);
                resource.delete();
                return "y";
            } catch (Exception e) {
                e.printStackTrace();
                return "n";
            }
        }
    }

    2.3.2 controller层

    package com.lin.controller;
    
    import java.io.File;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.annotation.Resource;
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.multipart.MultipartFile;
    import org.springframework.web.multipart.MultipartHttpServletRequest;
    import org.springframework.web.multipart.MultipartResolver;
    import org.springframework.web.multipart.commons.CommonsMultipartResolver;
    import org.springframework.web.servlet.config.VelocityConfigurerBeanDefinitionParser;
    
    import com.lin.domain.data.ResData;
    import com.lin.domain.data.ResListData;
    import com.lin.domain.error.Error;
    import com.lin.domain.sysUser.SysUser;
    import com.lin.domain.sysUser.SysUserWithDep;
    import com.lin.service.SysUserService;
    import com.lin.utils.Aes;
    import com.lin.utils.DateTimeUtils;
    import com.lin.utils.ResponseUtils;
    import com.lin.utils.Upload;
    import com.lin.utils.Utils;
    import com.sun.jersey.api.client.Client;
    
    import net.sf.json.JSONObject;
    
    /**
     * 后台用户-controller
     * @author libo
     */
    @Controller
    @RequestMapping("/sysUser")
    public class SysUserController {
    
        @Resource
        private SysUserService sysUserService;
        
        @Value(value="${imgPath}")    //后台图片保存地址
        private String imgPath;
        
        @Value(value="${uploadHost}")
        private String uploadHost;    //项目host路径    
        
        /**
         * 后台用户登陆功能
         * @return
         * @throws IOException 
         */
        @ResponseBody
        @RequestMapping(value="/login.do", method=RequestMethod.POST)
        public void login(HttpServletRequest req, HttpServletResponse res, 
                @RequestParam(required=true) String loginEmail, 
                @RequestParam(required=true) String loginPwd) throws IOException{
            //代码省略
        }

    /** * 根据id查询用户信息(包括部门信息) * @param req * @param res * @param id * @throws IOException */ @ResponseBody @RequestMapping(value="/getSysUser.do", method=RequestMethod.GET) public void getSysUser(HttpServletRequest req, HttpServletResponse res, @RequestParam(required=true) Integer id) throws IOException{   //代码省略 } /** * 更新后台用户信息 * @param req * @param res * @throws IOException */ @ResponseBody @RequestMapping(value="/updateSysUser.do" ,method=RequestMethod.POST) public void updateSysUser(HttpServletRequest req, HttpServletResponse res) throws IOException{ //代码省略 } /** * 添加用户 * @param req * @param res * @throws IOException */ @ResponseBody @RequestMapping(value="/addSysUser.do", method=RequestMethod.POST) public void addSysUser(HttpServletRequest req, HttpServletResponse res) throws IOException { //代码省略 }


    /** * 上传用户头像 * @param request * @param response */ @ResponseBody @RequestMapping(value="uploadSysHeadImg.do", method=RequestMethod.POST) public void uploadSysHeadImg(HttpServletRequest request,HttpServletResponse response){ JSONObject jo = new JSONObject(); try { MultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext()); MultipartHttpServletRequest Murequest = resolver.resolveMultipart(request); Map<String, MultipartFile> files = Murequest.getFileMap();//得到文件map对象
           // 实例化一个jersey Client client = new Client(); List<String> fileNameList = new ArrayList<>(); List<String> relaPathList = new ArrayList<>(); List<String> realPathList = new ArrayList<>(); for(MultipartFile pic: files.values()){ String uploadInfo = Upload.upload(client, pic, request, response, uploadHost, imgPath);
                    if(!"".equals(uploadInfo)){    //上传成功
                        String[] infoList = uploadInfo.split(";");
                        fileNameList.add(infoList[0]);    //文件名
                        relaPathList.add(infoList[1]);    //相对路径
                        realPathList.add(infoList[2]);    //真实完整路径
                    }else{    //上传失败
                        fileNameList.add("");
                        relaPathList.add("");
                        realPathList.add("");
                    } } jo.put(
    "success", 1); jo.put("error", null); jo.put("fileNameList", fileNameList); jo.put("relaPathList", relaPathList); jo.put("realPathList", realPathList); }catch (Exception e) { jo.put("success", 0); jo.put("error", "上传失败"); } ResponseUtils.renderJson(response, jo.toString()); } }

    其他的java文件省略,然后运行java项目

    三、前端部分

    3.1 index1-cropper图片剪切上传

    <!DOCTYPE html>
    <html>
    <head>
        <title>index1-cropper图片剪切上传</title>
        <meta charset="utf-8"/>
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <link rel="stylesheet" href="lib/cropper/dist/cropper.min.css" />
    </head>
    <body>
    
    <!-- accept="image/*,camera":表示允许调用相册和摄像头,capture="camera":表示直接打开摄像头-->
    <!--<input id="btn1" type="file" accept="image/*,camera" capture="camera" style="opacity: 0;"/>-->
    <input id="btn1" type="file" accept="image/*,camera" style="opacity: 0;"/>
    
    <div>
        <div>上传之前的图片</div>
        <img id="face_image" style="50px;height:50px;border-radius: 25px;border: 1px solid #fff;"/>
        <div>上传之后服务器的图片</div>
        <img id="success_image" style="50px;height:50px;border-radius: 25px;border: 1px solid #fff;"/>
    </div>
    <div>
        <button id="upload_btn">上传头像</button>
        <button id="image_save">保存</button>
        <span></span>
    </div>
    
    <div class="upload-img" style="300px;height: 300px;">
        <img src=""/>
    </div>
    
    <script src="jquery.min.js"></script>
    <script src="lib/cropper/dist/cropper.min.js"></script>
    <script src="lib/canvas-toBlob/canvas-toBlob.js"></script>
    
    <script>
        $(function() {
            //触发input file
            $('#upload_btn').click(function() {
                console.log('模拟点击。。。');
                $('#btn1').trigger('click');
            });
    
            //图片上传
            var $image = $('.upload-img > img');
            $image.cropper({
                viewMode: 1,
    //            preview: '.img-preview', //不同尺寸预览区
                aspectRatio: 1, //裁剪比例,NaN-自由选择区域
                autoCropArea: 0.7, //初始裁剪区域占图片比例
                crop: function(data) { //裁剪操作回调
                    console.log(data);
                }
            });
            var fileName; //选择上传的文件名
            $('#btn1').change(function(){
                var file = this.files[0];
                fileName = file.name;
                var reader = new FileReader();
                //reader回调,重新初始裁剪区
                reader.onload = function(){
                    // 通过 reader.result 来访问生成的 DataURL
                    var url = reader.result;
                    //选择图片后重新初始裁剪区
                    $image.cropper('reset', true).cropper('replace', url);
                };
                reader.readAsDataURL(file);
            });
    
            /*
             * 上传图片
             */
            $('#image_save').click(function() {
                var type = $image.attr('src').split(';')[0].split(':')[1];
    
                var canVas = $image.cropper("getCroppedCanvas", {});
                //将裁剪的图片加载到face_image
                $('#face_image').attr('src', canVas.toDataURL());
                canVas.toBlob(function(blob) {
                    var formData = new FormData();
                    formData.append("file", blob, fileName);
                    http://172.16.5.102:9000/index1-cropper%E5%9B%BE%E7%89%87%E5%89%AA%E5%88%87%E4%B8%8A%E4%BC%A0.html
                    $.ajax({
                        type: "POST",
                        url: 'http://172.16.5.102:8081/ssm_project/sysUser/uploadSysHeadImg.do',
                        data: formData,
                        contentType: false, //必须
                        processData: false, //必须
                        dataType: "json",
                        success: function(res){
                            //清空上传文件的值
                            $('#btn1').val('');
                            $('#success_image').attr('src', res.realPathList[0]);
                        },
                        error : function() {
                            //清空上传文件的值
                            $('#btn1').val('');
                        }
                    });
                }, type);
            });
    
            //取消
            $("#image_cancel").click(function() {
                //清空上传文件的值
                $(_pageId + inputFileId).val('');
            });
        });
    </script>
    </body>
    </html>

    效果图:

     

    3.2 index2-jquery-Form表单提交

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <!-- 选择图片后,就开始上传 -->
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <title>index2-jquery-Form表单提交</title>
        <script src="jquery.min.js"></script>
        <script src="jquery.form.js"></script>
    </head>
    <body>
    <img height="100" id="success_img"/>
    <form id="jvForm" action="o_save.shtml" method="post" enctype="multipart/form-data">
        <!-- 保存图片的相对路径,方便提交给后台,存到数据库 -->
        <input type="hidden" name="" id="img_path"/>
    
        <input type="file" id="select_file" onchange="uploadPic()" name="pic12"/>
    </form>
    
    <script>
        //上传图片
        function uploadPic(){
            //定义参数
            var options = {
                url:"http://172.16.5.102:8081/ssm_project/sysUser/uploadSysHeadImg.do",
                type:"post",
                dataType:"json",
                success:function(res){
                    $('#success_img').attr('src', res.realPathList[0]); //真实完整路径
                    $('#img_path').val(res.relaPathList[0]);    //相对路径
                }
            };
            //jquery.form使用方式
            $("#jvForm").ajaxSubmit(options);
        }
    </script>
    </body>
    </html>

    效果图:

    3.3 index3-jquery-ajax提交

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <!-- 选择图片后,需要点击提交按钮,才开始上传,可以不需要form标签 -->
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <title>index3-jquery-ajax提交</title>
        <script src="jquery.min.js"></script>
    </head>
    <body>
    <img id="success_img" height="100px">
    <br>
    
    <input type="file" id="upload_file">
    
    <!-- 保存图片的相对路径,方便提交给后台,存到数据库 -->
    <input type="hidden" name="" id="img_path"/>
    <input type="button" id="uploadPicButton" value="上传">
    
    <div>
        <a href="" id="download" download=""></a>
    </div>
    <script>
        //上传图片
        $('#uploadPicButton').click(function () {
            var pic = $('#upload_file')[0].files[0];
            var fd = new FormData();
            fd.append('uploadFile', pic);
            $.ajax({
                url:"http://172.16.5.102:8081/ssm_project/sysUser/uploadSysHeadImg.do",
                type:"post",
                data: fd,   // Form数据
                cache: false,
                contentType: false,
                processData: false,
                success:function(res){
                    $('#success_img').attr('src', res.realPathList[0]); //真实完整路径
                    $('#img_path').val(res.relaPathList[0]);    //相对路径
    
                    $('#download').html(res.fileNameList[0]);
                    $('#download').attr('href', res.realPathList[0]);
                    $('#download').attr('download', res.fileNameList[0]);
                }
            });
        })
    </script>
    </body>
    </html>

    效果图:

    3.4 index4-WebUploader多文件上传

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <title>index4-WebUploader多文件上传</title>
        <link rel="stylesheet" href="lib/webuploader/dist/webuploader.css">
        <script src="jquery.min.js"></script>
        <script src="lib/webuploader/dist/webuploader.js"></script>
        <style>
            .file-item {
                display: inline-block;
                text-align: center;
                font-size: 12px;
                margin: 10px;
            }
            .file-item .progress {
                position: relative;
                height: 6px;
                width: 100%;
                background-color: #ddd;
            }
            .file-item .progress span {
                position: absolute;
                left: 0;
                top: 0;
                width: 0%;
                height: 6px;
                background-color: dodgerblue;
            }
            .suc-img-item {
                display: inline-block;
                height: 100px;
                margin: 10px;
            }
        </style>
    </head>
    <body>
    
    <h3>图片上传</h3>
    <!--dom结构部分-->
    <div id="uploader-demo">
        <h4>上传前缩略图</h4>
        <div id="fileList" class="uploader-list"></div>
        <div id="upInfo"></div>
    
        <h4>上传后预览图</h4>
        <div id="successImgList">
                <!--<img class="suc-img-item" src="http://172.16.5.102:8090/upload/4337bd72-57d3-4d26-b94e-61193e9fe440.jpg">-->
                <!--<img class="suc-img-item" src="http://172.16.5.102:8090/upload/4337bd72-57d3-4d26-b94e-61193e9fe440.jpg">-->
        </div>
    
        <div id="filePicker">选择文件</div>
    </div>
    <input type="button" id="btn" value="开始上传">
    <script>
    //    // 图片上传demo
        $(function() {
            var $ = jQuery,
                $list = $('#fileList'),
                $successImgList = $('#successImgList'),
                ratio = window.devicePixelRatio || 1,  // 优化retina, 在retina下这个值是2 (window.devicePixelRatio是设备上物理像素和设备独立像素(device-independent pixels (dips))的比例)
                thumbnailWidth = 50 * ratio,   // 缩略图宽度
                thumbnailHeight = 50 * ratio,  // 缩略图高度
                uploader;    // Web Uploader实例
    
            // 初始化WebUploader
            uploader = WebUploader.create({
                auto: false,   // 自动上传
                swf:'../js/Uploader.swf',   // swf文件路径
                server: 'http://172.16.5.102:8081/ssm_project/sysUser/uploadSysHeadImg.do',  // 文件接收服务端接口地址
                threads:'5',        //同时运行5个线程传输
                fileNumLimit:'10',  //文件总数量只能选择10个
    
                // 选择文件的按钮,可选
                pick: {
                    id:'#filePicker',  //选择文件的按钮
                    multiple:true      //允许可以同时选择多个图片
                },
    
                quality: 90,        // 图片质量,只有type为`image/jpeg`的时候才有效
                compressSize: 0,     // 单位字节,如果图片大小小于此值,不会采用压缩
                crop: true,        //是否同意剪切
    
                //限制传输文件类型,accept可以不写
                accept: {
                    title: 'Images',    //描述
                    extensions: 'gif,jpg,jpeg,bmp,png,mkv,mp4', //文件类型
                    mimeTypes: '*/*'    //mime类型(*/* 可以上传所有类型)
                },
    
                compress: false,    //是否启用压缩
                resize: false,      //尺寸不改变
                duplicate: false   //是否允许重复上传
            });
    
    
            // 当有文件添加进来的时候,创建img显示缩略图使用
            uploader.on('fileQueued', function(file) {
                var $li = $('<div id="' + file.id + '" class="file-item thumbnail">' +
                                '<img>' +
                                '<div class="info">' + file.name + '</div>' +
                                '<div class="progress"><span></span></div>' +
                            '</div>'),
                    $img = $li.find('img');
    
                $list.append($li);    // $list为容器jQuery实例
    
                // 创建缩略图
                // 如果为非图片文件,可以不用调用此方法。
                // thumbnailWidth x thumbnailHeight 为 50 x 50
                uploader.makeThumb(file, function(error, src) {
                    if (error) {
                        $img.replaceWith('<span>不能预览</span>');
                        return;
                    }
                    $img.attr('src', src);
                }, thumbnailWidth, thumbnailHeight);
            });
    
            // 文件上传过程中创建进度条实时显示。  uploadProgress事件:上传过程中触发,携带上传进度。 file:文件对象;percentage:传输进度 Nuber:类型
            uploader.on('uploadProgress', function(file, percentage){
                console.log(file);
                console.log(percentage);
                var $li = $('#'+file.id),
                    $percent = $li.find('.progress span');
    
                // 避免重复创建
                if (!$percent.length) {
                    $percent = $('<p class="progress"><span></span></p>').appendTo($li).find('span');
                }
                $percent.css('width', percentage * 100 + '%');
            });
    
            // 文件上传成功时候触发,给item添加成功class, 用样式标记上传成功。 file:文件对象,    response:服务器返回数据
            uploader.on('uploadSuccess', function(file,res) {
                $('#'+file.id).addClass('upload-state-done');
                $("#upInfo").html("<font color='red'>"+res._raw+"</font>");
                $successImgList.append('<img class="suc-img-item" src="'+res.realPathList[0]+'">');
            });
    
            // 文件上传失败                                file:文件对象 , code:出错代码
            uploader.on('uploadError', function(file,code) {
                var $li = $( '#'+file.id ),
                    $error = $li.find('div.error');
    
                // 避免重复创建
                if(!$error.length) {
                    $error = $('<div class="error"></div>').appendTo($li);
                }
                $error.text('上传失败!');
            });
    
            // 不管成功或者失败,文件上传完成时触发。 file: 文件对象
            uploader.on('uploadComplete', function( file ) {
                $('#'+file.id ).find('.progress').remove();
            });
    
            //绑定提交事件
            $("#btn").click(function() {
                console.log("上传...");
                uploader.upload();   //执行手动提交
                console.log("上传成功");
            });
    
        });
    </script>
    </body>
    </html>

    效果图:

    四、查看文件服务器Tomcat下上传的文件

     注:由于我是一个前端开发人员,只对后台java了解一点。如有更好的解决方案,希望大家一起讨论,共同进步。

  • 相关阅读:
    Base64编码与图片互转
    YUI Compressor–另一款压缩JS/CSS的小工具
    布局和展现相关的建议──给用户体验设计者
    实现左右边框的最低碳代码~~
    三角的一个特殊做法(一个奇技淫巧~)
    数组指针和指针数组
    vs2008建win32基本项目
    vs2008快捷键
    (转)HTML特殊字符
    (转)html5 Placeholder属性兼容IE6、7方法
  • 原文地址:https://www.cnblogs.com/libo0125ok/p/7773898.html
Copyright © 2020-2023  润新知