首页 > 代码库 > Extjs4 + springMVC的文件上传

Extjs4 + springMVC的文件上传

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<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=http://www.mamicode.com/'public/images/{id}.gif'/>{text}">
显示效果:


写一个值对象:

/**
 * 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<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的默认访问路径都加上前缀和后缀,所以如果不记得加入以下这行代码的话,就会造成访问不了新上传的图片!

<!--允许静态资源访问-->

    <mvc:resources mapping="/upload/**" location="/upload/" />