用springMVC来做项目,如果遇到文件上传,那么一定要用spring自带的文件处理类来处理上传的文件,因为效率实在高过其他的。 从界面传过来的参数,如果设置了值对象,那么可以从值对象里面取出字符串类型的普通参数,如果不这样做,也可以直接从request里面获得,两种方法都可以。 问题是如果值对象里面写了其他类型的变量,妄想像Struts2那样处理,springMVC就会报出400 Bad Request的错误。 在Struts2里面,我们可以定义一个值对象为
- public class ImageVo {
- private String roomnumber;
-
- private File image1 ;
- private File image2 ;
- private File image3 ;
- }
复制代码
然后在后台从前台传过来的值对象里面取出image1……,那就是一个文件流了,非常好处理上传文件。但springMVC只能接受全部为string类型的字符串值,那么该怎么做呢? 前台Extjs4代码:
- /**
- * 图片添加
- * @type {Ext.form.Panel}
- */
- var addImageForm = new Ext.form.Panel({
- border: false, bodyPadding: 5, id: 'addImageForm',height:350,
- fieldDefaults: {labelWidth: 80, labelSeparator: ": ", anchor: '95%'},
-
- items: [
- {xtype:'fieldset',title:'图片上传', collapsible:true,
- items:[
- {
- xtype:'textfield',
- fieldLabel: '房间号码',
- name: 'roomnumber',
- id: 'roomnumber1',
- allowBlank: false,
- maskRe: /[\d]/,
- reegx: /[\d{4}]/,
- minLength: 4,
- maxLength: 4,
- emptyText: '请输入四位的房间号码(前两位代表楼层,后两位代表房间号)',
- regexText: '请输入正确的房间号码',
- //验证该房间号码是否存在 !
- listeners: {
- blur: function (e, t, eOpts) {
- var roomnumber = e.rawValue;
- if(roomnumber.length == 4){
- Ext.Ajax.request({
- method: 'post',
- params: {roomnumber: roomnumber},
- url: '/room/findroomhold',
- callback: function (options, success, response) {
- var jsonString = Ext.JSON.decode(response.responseText);
- if (jsonString.success) {
-
- } else {
- Ext.Msg.alert('警告', jsonString.msg);
- }
- }
- });
- }
- }
- }
- },{
- xtype:'filefield',
- fieldLabel:'上传图片1',
- name:'image1',
- id:'image1',
- buttonText:'',
- buttonConfig:{iconCls:'upload'},
- listeners:{
- change:function(btn, value, eOpts){
- var img_reg = /\.([jJ][pP][gG])小贝$|\.([jJ][pP][eE][gG])小贝$|\.([gG][iI][fF])小贝$|\.([pP][nN][gG])小贝$|\.([bB][mM][pP])小贝$/;
- if ( img_reg.test(value) ) {
- var img = Ext.getCmp('img1');
- var file = btn.fileInputEl.dom.files[0];
- var url = URL.createObjectURL(file);
- img.setSrc(url);
- } else {
- Ext.Msg.alert('提示', '请选择图片类型的文件!');
- return ;
- }
- }
- }
- },{
- xtype:'filefield',
- fieldLabel:'上传图片2',
- name:'image2',
- id:'image2',
- buttonText:'',
- buttonConfig:{iconCls:'upload'},
- listeners:{
- change:function(btn, value){
- var img_reg = /\.([jJ][pP][gG])小贝$|\.([jJ][pP][eE][gG])小贝$|\.([gG][iI][fF])小贝$|\.([pP][nN][gG])小贝$|\.([bB][mM][pP])小贝$/;
- if ( img_reg.test(value) ) {
- var img = Ext.getCmp('img2');
- var file = btn.fileInputEl.dom.files[0];
- var url = URL.createObjectURL(file);
- img.setSrc(url);
- } else {
- Ext.Msg.alert('提示', '请选择图片类型的文件!');
- return ;
- }
- }
- }
- },{
- xtype:'filefield',
- fieldLabel:'上传图片3',
- name:'image3',
- id:'image3',
- buttonText:'',
- buttonConfig:{iconCls:'upload'},
- listeners:{
- change:function(btn, value){
- var img_reg = /\.([jJ][pP][gG])小贝$|\.([jJ][pP][eE][gG])小贝$|\.([gG][iI][fF])小贝$|\.([pP][nN][gG])小贝$|\.([bB][mM][pP])小贝$/;
- if ( img_reg.test(value) ) {
- var img = Ext.getCmp('img3');
- var file = btn.fileInputEl.dom.files[0];
- var url = URL.createObjectURL(file);
- img.setSrc(url);
- } else {
- Ext.Msg.alert('提示', '请选择图片类型的文件!');
- return ;
- }
-
- }
- }
- }
- ]
- },{xtype:'fieldset',title:'图片预览',layout:'column',defaults:{width:130},
- items:[
- {xtype:'image',id:'img1'},
- {xtype:'image',id:'img2'},
- {xtype:'image',id:'img3'}
- ]
- }
- ],
- dockedItems: [
- {
- xtype: 'toolbar', dock: 'bottom', ui: 'footer', layout: {pack: 'center'},
- items: [
- {text: '确认上传', disabled: true, formBind: true, handler: function () {
- var form = this.up('form').getForm();
- if (form.isValid()) {
- form.submit({
- url: '/image/add',
- method: 'post',
- submitEmptyText: false,
- waitMsg: '请稍等,系统正在帮您添加',
- success: function (form, action) {
- //Ext.Msg.alert('成功', "上传成功!");
- Ext.Msg.alert('成功', action.result.msg);
- },
- failure: function (form, action) {
- Ext.Msg.alert('失败', action.result.msg);
- //Ext.Msg.alert('失败', "上传失败");
- }
- })
- }
- }},
- {text: '重置', handler: function () {
- this.up('form').getForm().reset();
- }}
-
- ]
- }
- ]
- });
复制代码
如图: ![](http://img.it-home.org/data/attachment/forum/2014pic/20140520151053406.jpg) 后台的java代码,因为只有一个非文件类的值,所以直接放到了参数里面了。
- import com.lhx.hotel.model.Image;
- import com.lhx.hotel.service.ImageService;
- import org.springframework.beans.factory.annotation.Autowired;
- 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 org.springframework.web.multipart.MultipartHttpServletRequest;
- import org.springframework.web.multipart.commons.CommonsMultipartResolver;
-
- import javax.servlet.http.HttpServletRequest;
- import java.io.File;
- import java.io.IOException;
- import java.util.*;
-
- /**
- * Created by xin on 14-5-18.
- */
- @Controller
- @RequestMapping("/image")
- public class ImageController {
-
- Map<String,Object> outmap = new HashMap<String, Object>();
-
- @Autowired
- private ImageService imageService ;
-
- @RequestMapping("/add")
- @ResponseBody
- public Map<String,Object> add(String roomnumber, HttpServletRequest request) throws IOException {
- List<String> fileTypes = new ArrayList<String>();
- fileTypes.add(".jpg");
- fileTypes.add(".jpeg");
- fileTypes.add(".bmp");
- fileTypes.add(".gif");
- fileTypes.add(".png");
- //是否成功上传了文件
- boolean ishasuploadimage = false ;
- //成功上传了n个图像
- int imageNum = 0 ;
- /**
- * 想通过ImageVo imageVo,但需要全部是string类型
- * 并且没有其他什么参数,大材小用,舍弃
- * String roomnumber = imageVo.getRoomnumber();
- */
- String imagepath = request.getRealPath("/upload");
- CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
- if (multipartResolver.isMultipart(request)){
- MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request ;
- //String roomnumber = multiRequest.getParameter("roomnumber");
- if (!"".equals(roomnumber) && roomnumber != null){
- int ronumber = Integer.valueOf(roomnumber) ;
- Iterator<String> iter = multiRequest.getFileNames();
- Image image = null ;
- while (iter.hasNext()){
- MultipartFile file = multiRequest.getFile((String)iter.next());
- //byte[] bytes = file.getBytes();
- //long size = file.getSize();
- //有上传文件的话,容量是大于0的。
- if (file.getSize() > 0){
- ishasuploadimage = true ;
- String imagename = file.getOriginalFilename();
- String ext = imagename.substring(imagename.lastIndexOf(".")) ;
- if (fileTypes.contains(ext)){
- //文件名为:房间号码 + image + 系统时间 + 后缀
- String fileName = roomnumber + "image" + System.currentTimeMillis() + ext ;
- image = new Image();
- image.setPhpath(fileName);
- image.setPhroomnumber(ronumber);
- File localFile = new File(imagepath,fileName);
- try {
- file.transferTo(localFile);
- imageService.insertSelective(image);
- imageNum ++ ;
- } catch (IOException e) {
- e.printStackTrace();
- outmap.put("success",false);
- outmap.put("msg","系统出错");
- return outmap ;
- }
- } else {
- outmap.put("success",false);
- outmap.put("msg","成功上传" + imageNum + "张图片,遇到不能上传的非图片类的文件而出错!");
- return outmap ;
- }
- }
-
- }
- } else {
- //这种情况很少见,除非直接在浏览器里面输入地址
- outmap.put("success",false);
- outmap.put("msg","没有对应的房间号");
- return outmap ;
- }
-
- }
- if (!ishasuploadimage){
- outmap.put("success",false);
- outmap.put("msg","没有上传文件");
- return outmap ;
- }
- outmap.put("success",true);
- outmap.put("msg","成功上传" + imageNum + "张图片!");
- return outmap ;
-
- }
- }
复制代码
这些代码是先写的,没什么注释,如果不是很看得懂,下面这个例子就详细点了 Extjs4前台代码:
- /**
- * Created by xin on 14-5-19.
- */
-
- var addStaffForm = new Ext.form.Panel({
- border: false, bodyPadding: 5, id: 'addStaffForm', height: 560,
- fieldDefaults: {labelWidth: 80, labelSeparator: ": ", anchor: '0', margin:'2 2 2 2'},
- items:[
- {
- xtype:'fieldset',
- defaultType: 'textfield',
- items: [
- {
- xtype: 'container',
- anchor: '-5',
- layout: 'column',
- items: [
- {xtype: 'textfield', width: 180, fieldLabel: "姓名", id: 'staffname', name: 'staffname',
- allowBlank: false, blankText: '姓名必须输入', emptyText: '请输入真实姓名'},
- {xtype: 'combobox', width: 180, fieldLabel: "性别", id: 'staffgender', name: 'staffgender', store: sexStore,
- valueField: 'text', value: '男', allowBlank: false, blankText: '请选择', labelAlign:'right',editable:false,
- listConfig: {
- getInnerTpl: function () {
- return "<img src='public/images/{id}.gif'/>{text}"
- }
- }}
- ]
- },
- {
- xtype: 'container',
- anchor: '-5',
- layout: 'column',
- items: [
- {xtype: 'textfield', fieldLabel: "职责", width: 180, id: 'staffprofession', name: 'staffprofession', emptyText: '请输入职责名称',
- allowBlank: false, blankText: '职责名称必须输入'},
- {xtype: 'textfield', fieldLabel: "部门", width: 180, id: 'staffdepartment', name: 'staffdepartment', allowBlank: false,labelAlign:'right'}
- ]
- },
- {
- xtype:'numberfield',
- fieldLabel: "月薪",
- id: 'staffsalary',
- name: 'staffsalary',
- anchor: '95%',
- step:50,
- maxValue:999999,
- allowBlank: true,
- minValue:0,
- negativeText:'月薪不能为负数',
- emptyText: '请填入月薪'
-
- },
- {
- xtype: 'fieldcontainer', fieldLabel: '电话', defaultType: 'textfield', layout: 'hbox', anchor: '95%',
- combineErrors: true,
- items: [
- {name: 'staffzone', id: 'staffzone', width: 50, emptyText: '区号', maskRe: /[\d]/, reegx: /[\d{3,4}]/,
- minLength: 3, maxLength: 4, regexText: '请输入正确的区号'},
- {xtype: 'label', text: '--'},
- {name: 'stafftelnumber', id: 'stafftelnumber', flex: 1, emptyText: '请输入电话号码', maskRe: /[\d]/, reegx: /[\d{7,8}]/,
- minLength: 7, maxLength: 8, regexText: '请输入正确的电话号码'}
- ]
- },
- {
- fieldLabel: '手机号码',
- name: 'staffmobile',
- id: 'staffmobile',
- allowBlank: true,
- anchor: '95%',
- maskRe: /[\d]/,
- reegx: /[\d{11}]/,
- minLength: 11,
- maxLength: 11,
- emptyText: '请输入手机号码',
- regexText: '请输入正确的手机号码'
- },
- {
- fieldLabel: '电子邮箱',
- name: 'staffemail',
- id: 'staffemail',
- allowBlank: true,
- anchor: '95%',
- emptyText: '请输入电子邮箱地址',
- vtype: 'email'
- },
- {
- xtype: 'fieldcontainer', fieldLabel: '地区', defaultType: 'combobox', layout: 'hbox', anchor: '95%',
- items: [
- {name: 'staffprovince', id: 'staffprovince', width: 90, emptyText: '请选择省', valueField: 'regionId', displayField: 'regionName',
- store: provinceStore, queryMode: 'local', triggerAction: 'all', selectOnFocus: true, forceSelection: true,editable:false,
- listeners: {
- change: function (f, newValue, oldValue) {
- var cityStore = Ext.data.StoreManager.lookup('cityStore');
- var city = this.up('form').getForm().findField('staffcity');
- var county = this.up('form').getForm().findField('staffcounty');
- if (newValue && newValue != oldValue) {
- city.setValue();
- county.setValue();
- cityStore.load({params: {parentId: newValue}});
- }
- }
- }
- },
- {name: 'staffcity', id: 'staffcity', width: 90, store: cityStore, emptyText: '请选择市', valueField: 'regionId',
- displayField: 'regionName',queryMode: 'local', triggerAction: 'all', selectOnFocus: true, forceSelection: true,
- editable:false,
- listeners: {
- change: function (f, newValue, oldValue) {
- var countyStore = Ext.data.StoreManager.lookup('countyStore');
- var county = this.up('form').getForm().findField('staffcounty');
- if (newValue && newValue != oldValue) {
- county.setValue();
- countyStore.load({params: {parentId: newValue}});
- }
- }
- }
- },
- {name: 'staffcounty', id: 'staffcounty', width: 90, store: countyStore, emptyText: '请选择区(县)', valueField: 'regionId',
- displayField: 'regionName',queryMode: 'local', triggerAction: 'all', selectOnFocus: true, editable:false,
- forceSelection: true}
- ]
- },
- {
- fieldLabel: '地址',
- name: 'staffpartaddress',
- id: 'staffpartaddress',
- allowBlank: true,
- emptyText: '请输入详细地址',
- anchor: '95%'
- },
- {
- xtype:'filefield',
- fieldLabel:'上传头像',
- name:'avatar',
- id:'avatar',
- anchor: '95%',
- buttonText:'',
- buttonConfig:{iconCls:'upload'},
- listeners:{
- change:function(btn,value){
- //是否是规定的图片类型
- var img_reg = /\.([jJ][pP][gG])小贝$|\.([jJ][pP][eE][gG])小贝$|\.([gG][iI][fF])小贝$|\.([pP][nN][gG])小贝$|\.([bB][mM][pP])小贝$/;
- if (img_reg.test(value)) {
- var img = Ext.getCmp('staffavatar');
- var file = btn.fileInputEl.dom.files[0];
- var url = URL.createObjectURL(file);
- img.setSrc(url);
- } else {
- Ext.Msg.alert('提示', '请选择图片类型的文件!');
- return ;
- }
- }
- }
- }
- ]
- },
- {
- xtype: 'fieldset',
- title: '图片预览', defaults: {margin:'1 1 1 100', width: 200,height:260},
- items: [
- {xtype: 'image', id: 'staffavatar',border: 2,
- style: {
- borderColor: 'blue',
- borderStyle: 'solid'
- }}
- ]
- }
- ],
- dockedItems: [
- {
- xtype: 'toolbar', dock: 'bottom', ui: 'footer', layout: {pack: 'center'},
- items: [
- {text: '添加', disabled: true, formBind: true, handler: function () {
- var form = this.up('form').getForm();
- if (form.isValid()) {
- form.submit({
- url: '/staff/add',
- method: 'post',
- submitEmptyText: false,
- waitMsg: '请稍等,系统正在帮您添加',
- success: function (form, action) {
- Ext.Msg.alert('成功', action.result.msg);
- //清除填过的内容
- //form.findField('guestname').setValue();
- },
- failure: function (form, action) {
- Ext.Msg.alert('失败', action.result.msg);
- }
- })
- }
- }},
- {text: '重置', handler: function () {
- this.up('form').getForm().reset();
- }}
-
- ]
- }
- ]
- });
复制代码
显示效果: ![](http://img.it-home.org/data/attachment/forum/2014pic/20140520151829734.jpg) 写一个值对象:
数据库的持久层对象就不写了,大同小异。处理的java类
- import com.lhx.hotel.model.Staff;
- import com.lhx.hotel.service.StaffService;
- import com.lhx.hotel.vo.StaffVo;
- import org.springframework.beans.factory.annotation.Autowired;
- 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 org.springframework.web.multipart.MultipartHttpServletRequest;
- import org.springframework.web.multipart.commons.CommonsMultipartResolver;
-
- import javax.servlet.ServletContext;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import javax.servlet.http.HttpSession;
- import java.io.File;
- import java.io.IOException;
- import java.util.*;
-
- /**
- * Created by xin on 14-5-20.
- */
- @Controller
- @RequestMapping("/staff")
- public class StaffController {
-
- //返回的map,会自动封装成json
- Map<String,Object> outmap = new HashMap<String, Object>();
-
- @Autowired
- private StaffService staffService ;
-
- @RequestMapping("/add")
- @ResponseBody
- public Map<String,Object> add(StaffVo staffVo, HttpServletRequest request, HttpServletResponse response){
- //持久层对象
- Staff staff = new Staff();
- /**
- * 基本信息的提取
- * 因为都是string类型,所有不可能为空,
- * 持久层对象属性同是string类型的,不用进行判断,
- * 非string类型的要进行判断,防止异常
- * extjs界面如果有格式限制的话,就不用trim处理,因为不允许输入空格
- * 没有限制的话还是要进行trim处理的
- * 对null进行trim处理会出现空指针异常,但幸亏传过来的值是空值""
- */
- String staffname = staffVo.getStaffname().trim();
- String staffgender = staffVo.getStaffgender();
- String staffprofession = staffVo.getStaffprofession().trim();
- String staffdepartment = staffVo.getStaffdepartment().trim();
-
- String staffzone = staffVo.getStaffzone();
- String stafftelnumber = staffVo.getStafftelnumber();
- String telphone = staffzone + stafftelnumber ;
-
- String staffmobile = staffVo.getStaffmobile();
-
- String staffemail = staffVo.getStaffemail();
- //地址,进行拼接
- String staffprovince = staffVo.getStaffprovince();
- String staffcity = staffVo.getStaffcity();
- String staffcounty = staffVo.getStaffcounty();
- String staffpartaddress = staffVo.getStaffpartaddress().trim();
- String address = staffprovince + staffcity + staffcounty + staffpartaddress ;
-
- //非string类型,要进行判断
- String staffsalary = staffVo.getStaffsalary();
- if (!"".equals(staffsalary)){
- double salary = Double.valueOf(staffsalary);
- staff.setStsalary(salary);
- }
- //后加的工号 年份月份加序号(位数不够前面加0)
- Calendar c = Calendar.getInstance();
- int year = c.get(Calendar.YEAR);
- int month = c.get(Calendar.MONTH);
- int staffnum = staffService.getrecordSize() ;
- String staffnumstr=String.valueOf(staffnum);
- String [] ss = {"00000","0000","000","00","0",""};
- staffnumstr = ss[staffnumstr.length()-1] + staffnumstr;
- String stjobnumber = year + "" + month + staffnumstr;
- /**
- * 填充到持久层对象中
- */
- staff.setStname(staffname);
- staff.setStgender(staffgender);
- staff.setStprofession(staffprofession);
- staff.setStdepartment(staffdepartment);
- staff.setSttelphone(telphone);
- staff.setStmobile(staffmobile);
- staff.setStemail(staffemail);
- staff.setStaddress(address);
- staff.setStjobnumber(stjobnumber);
- /**
- * 对上传文件进行处理
- */
- //获取servlet上下文
- ServletContext servletContext = request.getSession().getServletContext();
- //spring的文件处理解析类,包装了servlet的上下文。
- CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(servletContext);
- //是否有上传文件
- boolean hasUploadAvatar = false ;
- //如果是multipart的提交,这个判断有点多余,不过还是加上吧!
- if (multipartResolver.isMultipart(request)) {
- //把request请求进行升级,request有的,它都有,
- MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
- /**
- * String staffname = multiRequest.getParameter("staffname");
- * 这样也可以获得上面从staffVo里面取出的值
- */
- //获得上传文件的名称
- Iterator<String> iter = multiRequest.getFileNames();
- //如果有的话就依次取出来
- while (iter.hasNext()){
- //包装过的文件流
- MultipartFile file = multiRequest.getFile((String)iter.next());
- //这里要进行判断,即使是空值,没有上传内容,file都是有值(空值)的,而文件流大小要大于0才是有上传的东西
- if (file.getSize() > 0){
- //获得上传文件原始名
- String imagename = file.getOriginalFilename();
- //算出后缀名
- String ext = imagename.substring(imagename.lastIndexOf(".")) ;
- //对文件类型进行判断,这个操作也可以在前台进行处理,在前台进行处理比较好,前后台都进行处理最稳妥
- List<String> fileTypes = new ArrayList<String>();
- fileTypes.add(".jpg");
- fileTypes.add(".jpeg");
- fileTypes.add(".bmp");
- fileTypes.add(".gif");
- fileTypes.add(".png");
- //是图片再进行处理
- if (fileTypes.contains(ext.toLowerCase())){
- //文件名为:唯一的工号 + avatar + 系统时间 + 后缀
- String fileName = stjobnumber + "avatar" + System.currentTimeMillis() + ext ;
- //文件夹;String imagepath = request.getRealPath("/upload");过时的方法,用request.getSession().getServletContext()代替
- String avatarFolder = servletContext.getRealPath("/upload");
- File localFile = new File(avatarFolder,fileName);
- try {
- //直接写入到后台服务器,简单且快
- file.transferTo(localFile);
- staff.setStavatar(fileName);
- //保存资料到数据库中
- staffService.insertSelective(staff);
- outmap.put("success",true);
- outmap.put("msg","添加成功!");
- return outmap ;
- } catch (IOException e) {
- e.printStackTrace();
- outmap.put("success",false);
- outmap.put("msg","系统出错");
- return outmap ;
- }
- } else {
- outmap.put("success",false);
- outmap.put("msg","图片格式出错!");
- return outmap ;
- }
- }
- }
- }
- if (!hasUploadAvatar){
- staffService.insertSelective(staff);
- outmap.put("success",true);
- outmap.put("msg","添加成功!");
- return outmap ;
- }
- return null ;
- }
- }
-
复制代码
上传其他文件,把代码改一下就可以了……写这文章给自己做一个总结,也给其他人一个学习参考的选择。 自我总结的小技巧:文件上传,新建一个文件夹,比如upload。里面有个文件的话,部署后tomcat那边就有upload这个文件夹了,如果只是空的文件夹,部署可能不会自动生成,到时上传文件就找不到路径了。 上传文件要放入一个文件夹upload中,先前设置springMVC的默认访问路径都加上前缀和后缀,所以如果不记得加入以下这行代码的话,就会造成访问不了新上传的图片! |