异步上传

一. 实现异步上传
  之前要实现上传需要将表单的数据填写上, 并且选择文件之后一起将基本数据和文件提交到服务器
  现在要先将文件上传,之后再提交表单的基本数据,要实现这一的操作就需要异步上传(将文件的上传和表单的基本数据分开提交)
  我使用的是 webuploader 组件 实现异步上传,

步骤:
1.导入需要使用的相关 css 和 js

<head>
     <base  href="/MvcPro/">
    <title>异步上传</title>
    <!--表示样式可以根据设备的大小自适应-->
    <meta name="viewport" content="width=divce-width,initial-scale=1">
    <!--导入jq的js文件-->
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <!--导入bootstrap的js-->
    <script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
    <!--导入bootstrap的css文件-->
    <link rel="stylesheet" type="text/css" href="bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="webuploader/webuploader.css">
    <script src="webuploader/webuploader.js"></script>
</head>

2.定义出表单

<body>
 <div class="container"> 
   <div  class="row">
     <div  id="div1" class="col-md-8">
               <form id="tenantForm" method="post" action="tenant/add"  class="form-horizontal" name="tenantaddform">
          <!-- strut2  spring mvc -->
          <input name="formbean" value="cn.gzsxt.po.T_Tenant" type="hidden">
          <div class="form-group"  id="companynameDiv">
              <label class="col-sm-2 control-label">公司名称</label>
              <div class="col-md-5">
                  <input id="companyname" type="text"  placeholder="公司名称" name="companyname" class="form-control">
              </div>
              <div class="col-md-4" id="companynameMsg"></div>
          </div>
          <div class="hr-line-dashed"></div>
          <div class="form-group"  id="managernameDiv">
              <label class="col-sm-2 control-label">法人姓名</label>
              <div class="col-md-5">
                  <input   placeholder="法人姓名"  class="form-control" id="managername"  name="managername">
              </div>
               <div class="col-md-4" id="managernameMsg"></div>
          </div>
          <div class="hr-line-dashed"></div>
          <div class="form-group"  id="phoneDiv">
              <label class="col-sm-2 control-label">手机号</label>
              <div class="col-md-5">
                  <input type="text" placeholder="手机号" name="phone" id="phone" maxlength="11" class="form-control">
              </div>
              <div class="col-md-4" id="phoneMsg"></div>
          </div>
        <div class="hr-line-dashed"></div>
        <div class="form-group" id="identityDiv">
              <label class="col-sm-2 control-label">身份证号</label>
              <div class="col-md-5">
                  <input type="text" placeholder="身份证号" name="identity"  id="identity"  class="form-control">
              </div>
              <div class="col-md-4" id="identityMsg"></div>
          </div>
    <div class="hr-line-dashed"></div>
          <div class="form-group">
              <!-- div id; inp ty -------->
            <label class="col-sm-2 control-label">身份证正面</label>
            <div class="col-sm-10">
                  <div id="uploader" class="wu-example">
                      <!--用来存放文件信息-->
                      <div id="thelist1" class="uploader-list">
                      </div>
                      <div class="btns" id="idcard_id1">
                          <div id="picker1">选择文件</div>
                          <!-- button如果不指定   type 为button 默认是submit -->
                          <button id="ctlBtn1" type="button" class="btn btn-default">开始上传</button>
                      </div>
                  </div>
                  <!-- 身份证正面隐藏域表单,value是图片上传成功以后的 地址 -->
                  <input type="hidden" id="identitypositive"  name="identitypositive" />
              </div>
           </div>
          <div class="hr-line-dashed"></div>
          <div class="form-group">
          <!-- div id; inp ty id na -------->
            <label class="col-sm-2 control-label">身份证反面</label>
              <div class="col-sm-10">
                  <div id="uploader" class="wu-example">
                      <!--用来存放文件信息-->
                      <div id="thelist2" class="uploader-list"></div>
                      <div class="btns"  id="idcard_id2">
                          <div id="picker2">选择文件</div>
                           <div>
                           <!--
                              button如果不指定   type 为button 默认是submit
                            <button id="ctlBtn" class="btn btn-default">开始上传</button> -->
                              <button id="ctlBtn2" type="button" class="btn btn-default">开始上传</button>
                           </div>
                           <!-- 身份证反面隐藏域表单,value是图片上传成功以后的 地址 -->
                          <input type="hidden" id="identitynegative"  name="identitynegative" />
                      </div>
                  </div>
              </div>
           </div>
           <div class="hr-line-dashed"></div>
          <div class="form-group">
            <label class="col-sm-2 control-label">营业执照照片</label>
              <div class="col-sm-10">
                <!-- div id; inp ty id na -------->
              </div>
           </div>

          <div class="form-group">
              <div class="col-sm-4 col-sm-offset-2">
                  <button class="btn btn-primary" type="submit">保存内容</button>
                  <button class="btn btn-white" type="submit">取消</button>
              </div>
          </div>
      </form>
    </div>
  </div>
 </div>
<body>

3.定义出异步上传的 js

 <script>
//身份证正面
jQuery(function() {
        var list = $('#thelist1'), // thelist节点中添加文本  身份证正面  div添加
            btn = $('#ctlBtn1'), // 文件上传按钮   身份证正面 文件上传按钮
            state = 'pending',//当前文件的状态是等待上传状态
            uploader;
        //初始化
        uploader = WebUploader.create({ //对上传的基本要求配置
            // 不压缩image
            resize: false,
            // 文件接收服务端,上传该文件的服务器路径
            server: "emp/upload",
            // 选择文件的按钮。可选。
            //需要上传的文件所在的div
            pick: '#picker1' ,
           //只允许选择图片文件。
            accept: {
                title: 'Images',
                extensions: 'jpg,jpeg,bmp,png,gif',//允许上传的文件的格式
                mimeTypes: 'image/*'
            },
            //允许上传的文件个数
            fileNumLimit:2,
            //单个文件最大的上传限制 1M
            fileSingleSizeLimit : 1024 * 1024*5 // 5M
        });
        // 当有文件添加进来的时候触发的函数
        uploader.on( 'fileQueued', function(file) {
            console.log(file.id)
            //file.id表示添加进来的文件的编号(上传组件生成的)
            //file.name  表示上传文件的原名称
            list.append('<div id="' + file.id + '" class="item">' +
                '<h4 class="info">' + file.name + '</h4>' +
                '<p class="state">等待上传...</p>' +
            '</div>' );
        });
        // 'uploadProgress':文件上传过程中创建进度条实时显示。这是结合Bootstrap控制的样式
        // percentage  文件上传的百分比
        //file 上传的文件对象,是上传组件创建的
        uploader.on( 'uploadProgress', function( file,percentage){
            var li = $( '#'+file.id ),
            //在$li 代表的节点查找 是否有 进度条的样式,如果有则$percent的长度大于0 否则等于0
            percent=li.find('.progress .progress-bar');
            // 避免重复创建
            if (!percent.length ) {
                //追加一个进度条样式
                percent = $('<div class="progress progress-striped active">' +
                  '<div class="progress-bar" role="progressbar" style=" 0%">' +
                  '</div>' +
                '</div>').appendTo(li).find('.progress-bar');
//              $('<div class="progress progress-striped active">' +
//                '<div class="progress-bar" role="progressbar" style=" 0%">' +
//                '</div>' +
//              '</div>').appendTo($li);
//              $percent=$li.find('.progress-bar');
            }
            li.find('p.state').text('上传中');
            percent.css( 'width', percentage * 100 + '%' );
        });
        //'uploadSuccess':文件上传成功后  触发的事件  触发一个回调函数
        //response 表示服务器端返回的数据
        //response:该对象封装了服务器端返回的数据,要取得返回的数据需要用到该对象的“_raw”属性
        //writer.print(this.getDir() + newFileName);
        uploader.on( 'uploadSuccess', function(file,response){
            // 上传的图片保存的相对位置(文件上传到服务器端之后保存的路径信息)
            var idcard_url = response._raw;
             $("#idcard_id1").append("<br><img  src='"+idcard_url+"' style=' 150px;height: 150px' />");
             //将url 添加到  form表单的隐藏域中,方便最后提交信息的时候将文件的名称保存到数据库
             $("#identitypositive").val(idcard_url);
             $('#'+file.id ).find('p.state').text('已上传');
        });
        uploader.on( 'uploadError', function( file ) {
            $( '#'+file.id ).find('p.state').text('上传出错');
        });
        uploader.on( 'uploadComplete', function( file ) {
            $( '#'+file.id ).find('.progress').fadeOut();
        });
        uploader.on( 'all', function( type ) {
            if ( type === 'startUpload' ) {
                state = 'uploading';
            } else if ( type === 'stopUpload' ) {
                state = 'paused';
            } else if ( type === 'uploadFinished' ) {
                state = 'done';
            }
            if ( state === 'uploading' ) {
                btn.text('暂停上传');
            } else {
                btn.text('开始上传');
            }
        });
        //出错以后回调的函数
        uploader.on("error",function(type){
            alert(type);
            if(type == "F_EXCEED_SIZE"){
                layer.alert('最大只能上传1M文件', {
                      skin: 'layui-layer-molv' //样式类名
                });
            }
        });
        btn.on( 'click', function() {
            if (state === 'uploading' ) {
                uploader.stop();
            } else {
                uploader.upload();
            }
        });
    });
 //身份证反面
    jQuery(function() {
        var list = $('#thelist2'), // thelist节点中添加文本  身份证正面  div添加
            btn = $('#ctlBtn2'), // 文件上传按钮   身份证正面 文件上传按钮
            state = 'pending',
            uploader;
        //初始化
        uploader = WebUploader.create({
            // 不压缩image
            resize: false,
            // 文件接收服务端路径。
            server: "emp/upload",
            // 选择文件的按钮。可选。
            // 内部根据当前运行是创建,可能是input元素,也可能是flash.
                //开始上传 按钮的id
            pick: '#picker2',
                 // 只允许选择图片文件。
            accept: {
                title: 'Images',
                extensions: 'jpg,jpeg,bmp,png',
                mimeTypes: 'image/*'
            },
            //允许上传的文件个数
            fileNumLimit:2,
            //单个文件最大的上传限制 1M
            fileSingleSizeLimit : 5*1024 * 1024 // 1M
        });
        // 当有文件添加进来的时候
        uploader.on( 'fileQueued', function(file) {
            list.append( '<div id="' + file.id + '" class="item">' +
                '<h4 class="info">' + file.name + '</h4>' +
                '<p class="state">等待上传...</p>' +
            '</div>' );
        });
        // 文件上传过程中创建进度条实时显示。
        uploader.on( 'uploadProgress', function( file, percentage ) {
            var li = $( '#'+file.id ),
                percent =li.find('.progress .progress-bar');
            // 避免重复创建
            if (!percent.length ) {
                percent = $('<div class="progress progress-striped active">' +
                  '<div class="progress-bar" role="progressbar" style=" 0%">' +
                  '</div>' +
                '</div>').appendTo(li).find('.progress-bar');
            }
            li.find('p.state').text('上传中');
            percent.css( 'width', percentage * 100 + '%' );
        });
        //文件上传成功后  触发的事件  触发一个回调函数
        uploader.on( 'uploadSuccess', function( file,response) {
            // 上传的图片保存的相对位置
            var idcard_url = response._raw;
             $("#idcard_id2").append("<img  src='"+idcard_url+"' style=' 150px;height: 150px' />");
             //将url 添加到  form表单的隐藏域中
             $("#identitynegative").val(idcard_url);
            $( '#'+file.id ).find('p.state').text('已上传');
        });
        uploader.on( 'uploadError', function( file ) {
            $( '#'+file.id ).find('p.state').text('上传出错');
        });
        uploader.on( 'uploading', function( file ) {
            $( '#'+file.id ).find('p.state').text('上传中...');
        });
        uploader.on( 'uploadComplete', function( file ) {
            $( '#'+file.id ).find('.progress').fadeOut();
        });
        uploader.on( 'all', function( type ) {
            if ( type === 'startUpload' ) {
                state = 'uploading';
            } else if ( type === 'stopUpload' ) {
                state = 'paused';
            } else if ( type === 'uploadFinished' ) {
                state = 'done';
            }
            if ( state === 'uploading' ) {
                btn.text('暂停上传');
            } else {
                btn.text('开始上传');
            }
        });
      //出错以后回调的函数
        uploader.on("error",function(type){
            if(type == "F_EXCEED_SIZE"){
                layer.alert('最大只能上传1M文件', {
                      skin: 'layui-layer-molv' //样式类名
                });
            }
        });
        btn.on( 'click', function() {
            if ( state === 'uploading' ) {
                uploader.stop();
            } else {
                uploader.upload();
            }
        });
    });
    </script>

4.定义出开发后端上传代码

public abstract class BaseServlte extends HttpServlet {
    SmartUpload smart=null;
    String newFileName = null;
    //保存文件
    public void saveFile(HttpServletRequest req, HttpServletResponse resp) {
        //照片处理
        try {
            //1.实例化上传的工具类对象
            smart = new SmartUpload();
            //2.获取 config 内置对象
            ServletConfig config = this.getServletConfig();
            //3.初始化
            smart.initialize(config,req,resp);
            //4.设置相关参数 (允许上传的文件类型)
            smart.setAllowedFilesList("jpg,png,gif");
            //4.1 设置单个文件的最大值
            smart.setMaxFileSize(1024*1024*1024*5);
            //4.2 设置所有文件的最大值
            smart.setTotalMaxFileSize(1024*1024*1024*5*10);
            //5.实现上传 (将文件放到内存, 还没有保存到磁盘)
            smart.upload();
            //6.获取项目部署路径
            String filepath = req.getServletContext().getRealPath("/" + this.getDir());
            File file = new File(filepath);
            if (!file.exists()) {
                file.mkdirs();
            }
            //7按照文件原名称保存
            //smart.save(savePath);
            //7.1.为文件重命名保存 (避免覆盖)
            if (smart.getFiles().getFile(0).getSize()>0) { //有文件才进行上传
                //取得文件扩展名
                String ext = smart.getFiles().getFile(0).getFileExt();
                //生成新的文件名 
                String fileName = UUID.randomUUID().toString().replaceAll("-", "");
                newFileName = this.getDir() + fileName + "." + ext;
                //按照新的文件名保存文件, 获取的是第一张照片对象就直接抵用该对象的 saveAs 方法实现保存
                smart.getFiles().getFile(0).saveAs(filepath + fileName + "." + ext);
                PrintWriter writer = resp.getWriter();
                writer.print(newFileName);
                writer.close();
            } else {
                throw new Exception("文件为空");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    //增加一个抽象方 子类必须实现(文件夹的名字交给子类决定)
    public abstract String getDir();
}
原文地址:https://www.cnblogs.com/yslf/p/10846680.html