异步上传
一. 实现异步上传
之前要实现上传需要将表单的数据填写上, 并且选择文件之后一起将基本数据和文件提交到服务器
现在要先将文件上传,之后再提交表单的基本数据,要实现这一的操作就需要异步上传(将文件的上传和表单的基本数据分开提交)
我使用的是 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="width: 0%">' + '</div>' + '</div>').appendTo(li).find('.progress-bar'); // $('<div class="progress progress-striped active">' + // '<div class="progress-bar" role="progressbar" style="width: 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='width: 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="width: 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='width: 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(); }