用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]){1}$|\.([jJ][pP][eE][gG]){1}$|\.([gG][iI][fF]){1}$|\.([pP][nN][gG]){1}$|\.([bB][mM][pP]){1}$/;
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]){1}$|\.([jJ][pP][eE][gG]){1}$|\.([gG][iI][fF]){1}$|\.([pP][nN][gG]){1}$|\.([bB][mM][pP]){1}$/;
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]){1}$|\.([jJ][pP][eE][gG]){1}$|\.([gG][iI][fF]){1}$|\.([pP][nN][gG]){1}$|\.([bB][mM][pP]){1}$/;
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();
}}
]
}
]
});
后台的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 outmap = new HashMap();
@Autowired
private ImageService imageService ;
@RequestMapping("/add")
@ResponseBody
public Map add(String roomnumber, HttpServletRequest request) throws IOException {
List fileTypes = new ArrayList();
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 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 "{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]){1}$|\.([jJ][pP][eE][gG]){1}$|\.([gG][iI][fF]){1}$|\.([pP][nN][gG]){1}$|\.([bB][mM][pP]){1}$/;
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();
}}
]
}
]
});
写一个值对象:
/**
* Created by xin on 14-5-20.
*/
public class StaffVo {
private String staffname ;
private String staffgender ;
private String staffprofession ;
private String staffdepartment ; // 部门
//如果改为double类型,这个上传的值不能为空值,所有改为string类型
private String staffsalary ; //月薪
private String staffzone ; //区号
private String stafftelnumber ; //号码
private String staffmobile ; //手机号码
private String staffemail ; //邮箱
private String staffprovince ;
private String staffcity ;
private String staffcounty ;
private String staffpartaddress ;
/**
* 这个file类型在这里是有问题的,不象struts可进行封装,如果有上传文件,
* 就不能整个对象传过去了,所有要进行删除
*/
//private File avatar ; //头像
public String getStaffname() {
return staffname;
}
public void setStaffname(String staffname) {
this.staffname = staffname;
}
public String getStaffgender() {
return staffgender;
}
public void setStaffgender(String staffgender) {
this.staffgender = staffgender;
}
public String getStaffprofession() {
return staffprofession;
}
public void setStaffprofession(String staffprofession) {
this.staffprofession = staffprofession;
}
public String getStaffdepartment() {
return staffdepartment;
}
public void setStaffdepartment(String staffdepartment) {
this.staffdepartment = staffdepartment;
}
public String getStaffsalary() {
return staffsalary;
}
public void setStaffsalary(String staffsalary) {
this.staffsalary = staffsalary;
}
public String getStaffzone() {
return staffzone;
}
public void setStaffzone(String staffzone) {
this.staffzone = staffzone;
}
public String getStafftelnumber() {
return stafftelnumber;
}
public void setStafftelnumber(String stafftelnumber) {
this.stafftelnumber = stafftelnumber;
}
public String getStaffmobile() {
return staffmobile;
}
public void setStaffmobile(String staffmobile) {
this.staffmobile = staffmobile;
}
public String getStaffemail() {
return staffemail;
}
public void setStaffemail(String staffemail) {
this.staffemail = staffemail;
}
public String getStaffprovince() {
return staffprovince;
}
public void setStaffprovince(String staffprovince) {
this.staffprovince = staffprovince;
}
public String getStaffcity() {
return staffcity;
}
public void setStaffcity(String staffcity) {
this.staffcity = staffcity;
}
public String getStaffcounty() {
return staffcounty;
}
public void setStaffcounty(String staffcounty) {
this.staffcounty = staffcounty;
}
public String getStaffpartaddress() {
return staffpartaddress;
}
public void setStaffpartaddress(String staffpartaddress) {
this.staffpartaddress = staffpartaddress;
}
}
数据库的持久层对象就不写了,大同小异。处理的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 outmap = new HashMap();
@Autowired
private StaffService staffService ;
@RequestMapping("/add")
@ResponseBody
public Map 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 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 fileTypes = new ArrayList();
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的默认访问路径都加上前缀和后缀,所以如果不记得加入以下这行代码的话,就会造成访问不了新上传的图片!