Ajax配合Spring如何实现文件上传功能

这篇文章将为大家详细讲解有关Ajax配合Spring如何实现文件上传功能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

站在用户的角度思考问题,与客户深入沟通,找到普兰店网站设计与普兰店网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:成都网站建设、成都网站设计、企业官网、英文网站、手机端网站、网站推广、域名与空间、雅安服务器托管、企业邮箱。业务覆盖普兰店地区。

一、 需求

Web表单页面,可以通过表单上传图片以及其他文字信息。

二、 图片上传的流程

之前没有做过这类页面,通过查询资料。发现比较常见的做法,是先将图片上传到服务器端的某个文件目录下,服务器向前台返回图片的存储路径;之后,前台将图片存储路径以及其他表单信息一起提交到服务器,所有的表单信息存储在数据库中。

三、 方法

由于项目需要,我这里介绍两种图片上传方法,第一种是使用ajax对一个图片直接上传;第二种是先在前台将图片切割为较小的文件,之后使用ajax分别上传图片到服务器,服务器实现对文件的拼接。(方法二适合较大文件的上传)下面我分别对两种方法做介绍。

方法一: 直接上传

1 html页面

 
 
 
" />    

 
 

 
 
这一部分需要注意的是,form表单的enctype属性必须设置为“multipart/form-data”,在Html5中,如果需要多张图片一起上传,可以在 标签中,增加multiple属性,例如:
 
 
 

 

2 js

 

(1)js使用ajax提供的ajaxfileupload.js库。这个库使用起来还是比较方便的,和普通的ajax函数使用方法几乎相同。首先,需要ajaxfileupload.js库文件。这里需要注意,我之前在网上下载了一个ajaxfileupload.js文件不能用,浪费了很长时间,我直接把js库文件粘贴到这里,方便分享。

 

// JavaScript Document// ajax file uplaod  jQuery.extend({    createUploadIframe: function(id, uri)    {      //create frame      var frameId = 'jUploadFrame' + id;      if(window.ActiveXObject) {        var io = document.createElement('');        if(typeof uri== 'boolean'){          io.src = 'javascript:false';        }        else if(typeof uri== 'string'){          io.src = uri;        }      }      else {        var io = document.createElement('iframe');        io.id = frameId;        io.name = frameId;      }      io.style.position = 'absolute';      io.style.top = '-1000px';      io.style.left = '-1000px';      document.body.appendChild(io);      return io;    },    createUploadForm: function(id, fileElementId)    {      //create form      var formId = 'jUploadForm' + id;      var fileId = 'jUploadFile' + id;      var form = jQuery('');      var oldElement = jQuery('#' + fileElementId);      var newElement = jQuery(oldElement).clone();      jQuery(oldElement).attr('id', fileId);      jQuery(oldElement).before(newElement);      jQuery(oldElement).appendTo(form);      //set attributes      jQuery(form).css('position', 'absolute');      jQuery(form).css('top', '-1200px');      jQuery(form).css('left', '-1200px');      jQuery(form).appendTo('body');      return form;    },    ajaxFileUpload: function(s) {      // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout       s = jQuery.extend({}, jQuery.ajaxSettings, s);      var id = s.fileElementId;      var form = jQuery.createUploadForm(id, s.fileElementId);      var io = jQuery.createUploadIframe(id, s.secureuri);      var frameId = 'jUploadFrame' + id;      var formId = 'jUploadForm' + id;      if( s.global && ! jQuery.active++ )      {        // Watch for a new set of requests        jQuery.event.trigger( "ajaxStart" );      }      var requestDone = false;      // Create the request object      var xml = {};      if( s.global )      {        jQuery.event.trigger("ajaxSend", [xml, s]);      }      var uploadCallback = function(isTimeout)      {        // Wait for a response to come back        var io = document.getElementById(frameId);        try        {          if(io.contentWindow)          {            xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;            xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;          }else if(io.contentDocument)          {            xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null;            xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document;          }        }catch(e)        {          jQuery.handleError(s, xml, null, e);        }        if( xml || isTimeout == "timeout")        {          requestDone = true;          var status;          try {            status = isTimeout != "timeout" ? "success" : "error";            // Make sure that the request was successful or notmodified            if( status != "error" )            {              // process the data (runs the xml through httpData regardless of callback)              var data = jQuery.uploadHttpData( xml, s.dataType );              if( s.success )              {                // ifa local callback was specified, fire it and pass it the data                s.success( data, status );              };              if( s.global )              {                // Fire the global callback                jQuery.event.trigger( "ajaxSuccess", [xml, s] );              };            } else            {              jQuery.handleError(s, xml, status);            }          } catch(e)          {            status = "error";            jQuery.handleError(s, xml, status, e);          };          if( s.global )          {            // The request was completed            jQuery.event.trigger( "ajaxComplete", [xml, s] );          };          // Handle the global AJAX counter          if(s.global && ! --jQuery.active)          {            jQuery.event.trigger("ajaxStop");          };          if(s.complete)          {            s.complete(xml, status);          } ;          jQuery(io).unbind();          setTimeout(function()          { try          {            jQuery(io).remove();            jQuery(form).remove();          } catch(e)          {            jQuery.handleError(s, xml, null, e);          }          }, 100);          xml = null;        };      }      // Timeout checker      if( s.timeout > 0 )      {        setTimeout(function(){          if( !requestDone )          {            // Check to see ifthe request is still happening            uploadCallback( "timeout" );          }        }, s.timeout);      }      try      {        var form = jQuery('#' + formId);        jQuery(form).attr('action', s.url);        jQuery(form).attr('method', 'POST');        jQuery(form).attr('target', frameId);        if(form.encoding)        {          form.encoding = 'multipart/form-data';        }        else        {          form.enctype = 'multipart/form-data';        }        jQuery(form).submit();      } catch(e)      {        jQuery.handleError(s, xml, null, e);      }      if(window.attachEvent){        document.getElementById(frameId).attachEvent('onload', uploadCallback);      }      else{        document.getElementById(frameId).addEventListener('load', uploadCallback, false);      }      return {abort: function () {}};    },    uploadHttpData: function( r, type ) {      var data = !type;      data = type == "xml" || data ? r.responseXML : r.responseText;      // ifthe type is "script", eval it in global context      if( type == "script" )      {        jQuery.globalEval( data );      }      // Get the JavaScript object, ifJSON is used.      if( type == "json" )      {        eval( "data = " + data );      }      // evaluate scripts within html      if( type == "html" )      {        jQuery("
").html(data).evalScripts();      }      return data;    },    handleError: function( s, xhr, status, e )   {      // If a local callback was specified, fire it       if ( s.error ) {        s.error.call( s.context || s, xhr, status, e );      }      // Fire the global callback      if ( s.global ) {        (s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );      }    }  });

 


 

(2)之后调用ajaxfileupload.js库,编写图片上传脚本,这里命名为ajaxfileuplaod_implement.js 

function fileUpload() {     var inputObject = $("#fileImage").get(0);    if(inputObject.value == "")    {      alert("清先选择需要上传的图片");      return false;    }    $.ajaxFileUpload({       url: '/PicSubmit/pic', //服务器端请求地址       secureuri: false, //是否需要安全协议,一般设置为false       type: 'post',      fileElementId: 'fileImage', //文件上传域的ID       dataType: 'text', //返回值类型 一般设置为json       enctype:'multipart/form-data',//注意一定要有该参数       success: function (data, status) //服务器成功响应处理函数       {         data=decodeURI(data);//服务器端使用urlencode将中文字符编码,所以这里需要解码。这样做的目的是防止中文乱码        var address = JSON.parse(data);        for(var i=0;i              //hiden标签的value值中,方法见下面的writeHide函数        }      },       complete: function(xmlHttpRequest)       { //这里将html中的文件上传标签替换为新的标签,是应为我在开发过程中发现,当ajax执行一次上传操作之后,再使用file标签选择文件时,标签没有反应,
   //所以暂时使用了这种方法。        inputObject.replaceWith('');      },      error: function (data, status, e)//服务器响应失败处理函数      {         //alert("无法连接到服务器");      }     })   }function writeHide(data){   if($("#addressid").get(0).value == "")   {     $("#addressid").get(0).value = data.newName;   }   else   {     $("#addressid").get(0).value = $("#addressid").get(0).value+","+data.newName;   }  } 

 

3 spring.

 

完成上面两个部分之后,前台的主要工作基本就结束了。我后台使用了spring框架。

 

首先是springMVC的配置文件:viewspace-servlet.xml

 

                                                                                                                                                             error_fileupload                     其中,类“org.springframework.web.multipart.commons.CommonsMultipartResolver”的配置是必须的,否则后台无法收到前台传来的文件。

 


 

 

为了防止文件名中的中文字符传输出现问题,在web.xml中做如下配置:

 

         contextConfigLocation    classpath:applicationContext.xml                  org.springframework.web.context.ContextLoaderListener                viewspace            org.springframework.web.servlet.DispatcherServlet                viewspace    /                characterEncodingFilter       org.springframework.web.filter.CharacterEncodingFilter                encoding         UTF-8                       forceEncoding         true                        characterEncodingFilter       /*       

 


 

接下来是重点,在Controller中,使用如下方式接受前台穿回来的文件。
 

 @RequestMapping(value="/pic") 
  @ResponseBody 
  public String submitPic(@RequestParam(value = "filename",required = false) MultipartFile[] fileImage,  
      HttpServletRequest request){ 
    if(fileImage == null){ 
      return "[]"; 
    } 
    return picSaveService.savePic(fileImage); 
  }

其中需要注意的是,如果前端html的input标签中使用了multiple属性,则表示标签支持上传多个图片,则controller的参数列表中,文件的类型使用MultipartFile[],反之,如果没有使用multiple属性,表示上传的是一张图片,则controller使用MultipartFile类型接收。 


 

文件接收完成后,就可以对文件进行存储了,方法有很多,我这里举一个例子如下:

 

  public String savePic(MultipartFile[] fileImage){      //为图片改名      String oldName = "";      String newName = "";      String extension = "";      //图片按照上传时间命名      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");      //存储每张图片的信息      List resultList = new ArrayList();      //获取配置文件中图片的存储路径      String path = Parameters.getInstance().getDatabaseProps().getProperty("pic_save_dir");      //依次将图片存储到path路径下      for(int i=0;i这里将接收到的图片的原始名称以及修改后存储使用的名称返回给前台,原始名称用于在前台页面输出“存储成功”的提示信息,修改后的名称用于给hiden标签复制,hiden标签的内容会在之后随表单中其他信息一起提交到服务端,通过hiden标签,我们就可以知道与表单关联的图片被存储在什么地方。
 
 

 

最后,图片上传完成后还需要提交表单,这里使用SpringMVC实现一个表单接收功能。这里名为address的参数,存储的就是图片的存储路径。

 

  @RequestMapping(value="/form")    public String submitForm(HttpServletRequest request){      String sid = request.getParameter("name");      String address = request.getParameter("address");            if(sid != null && submiter != null && faultTime != null && message != null && address != null){        if(formDataSaveService.saveForm(sid, submiter, message, address, faultTime)){          return "ac";        }      }      return "error";    }

方法二  前台切割上传(留着后面补充)

 


 

               

关于“Ajax配合Spring如何实现文件上传功能”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。


分享文章:Ajax配合Spring如何实现文件上传功能
分享链接:http://myzitong.com/article/ppocsh.html