ajaxfileupload跨域文件上传会遇到2个问题
1:跨域访问以json,xml格式返回,直接报406
网上查了设置服务器端直接设置header内容Access-Control-Allow-Origin:*
或者
Access-Control-Allow-Origin:www.test.com
起不到作用还是报406
2:跨域获取不到 body中的返回值
ajaxfileupload是通过iframe提交post表单形式实现异步不跳转上传,把值赋值在iframe 中的body标签。如果不涉及到跨域是直接能通过ajaxfileupload.js 92行
io.contentWindow.document.body 或则 io.contentWindow.document.XMLDocument 获取异步返回的值
但是一旦涉及到跨域访问,主流浏览器都是禁止获取值,就算是同域,如localhost:8080 与localhost:8088一样你也获取不到值,真气人啊哈哈。
不过你可以在chrom的debug模式中 敲打 io 能观察到是有返回值的,但是你就是获取不到,浏览器直接抛异常。
原理 详见 http://blog.csdn.net/joyhen/article/details/21631833
目前这个跨域解决方法,只适合主域相同,二级域名不同,或者端口号不同的业务场景,实现页面完全跨域,貌似目前官方也没给出完整方案,这涉及到网页安全问题了。
一.controller层
@RequestMapping(value = "upload.json", method = RequestMethod.POST) public @ResponseBody Object upload(/*@RequestParam MultipartFile file,*/ @RequestParam(value = "uploadType", required = false) String uploadType, HttpServletRequest request, HttpServletResponse response) { //1.解决跨域访问domain localhost String damain = "localhost"; String setDomain = "<script>document.domain = \""+damain+"\";</script>"; //2.获取上传文件MultipartFile流对象 MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request; Iterator<String> iter = multiRequest.getFileNames(); MultipartFile studentPhoto = null; while(iter.hasNext()){ studentPhoto = multiRequest.getFile(iter.next()); } //获取流之后就不要我说了吧,跨域返回 json,xml格式 报406错误 所以返回字符串没问题,如果哪位大神有好的解决方案可以留言 return "文件名称" }
二. JSP:页面
<div class="aboutBox"> <div > <p><span>身份证正面:</span> <span > <a href="#">选择照片</a> <input type="file" id="studentPhoto" name="studentPhoto" /> <input type="hidden" value="" id="cardnoPosUrl" name="cardnoPosUrl" /> </span> </p> <img src="" id="cardnoPosUrlShow" alt=""> </div> </div>
三.封装ajaxfileupload 支持单页多图上传
//调用uploadCommon.js $(".aboutBox").delegate("#studentPhoto","change",function() { UploadifyFileCommon.uploadOneImage("studentPhoto","cardnoPosUrlShow",'cardnoPosUrl',"personal"); }); //上传图片封装方法 uploadCommon.js var UploadifyFileCommon = { /** * @param FileDivId 上传文件的File 如:<input type="file" id="file" name="file" /> * @param showUrlId 显示图片的img 如: <img src="" id="showImg" alt=""> * @param saveUrlId 保存图片的相对路径 如:/enterprise/1232122.jpg * @param uploadType 图片的业务类型 如个人图片 personal * @returns {boolean} */ uploadOneImage:function(FileDivId,showUrlId,saveUrlId,uploadType){ //设置domain document.domain = "localhost"; $.ajaxFileUpload ( { url:'http://localhost:8088/upload/upload.json', //用于文件上传的服务器端请求地址 secureuri: false, //一般设置为false fileElementId: FileDivId, //文件上传空间的id属性 <input type="file" id="file" name="file" /> data: {//加入的文本参数 "uploadType": uploadType }, dataType: 'json', //返回值类型 一般设置为json success: function (data, status) //服务器成功响应处理函数 { //服务器地址 var serverUrl = "http://www.testimage.com"; if(data=="error"){ alert("上传图片失败"); return false; } //回显图片完整地址 $("#"+showUrlId).attr("src",serverUrl+ data); //赋值图片上传绝对路劲 $("#"+saveUrlId).val(data); }, error: function (data, status, e)//服务器响应失败处理函数 { console.log(data); } } ); return false; } };
四.修改ajaxfileupload.js 方法uploadhttpData返回值
jQuery.extend({ handleError: function( s, xhr, status, e ) { // If a local callback was specified, fire it if ( s.error ) s.error( xhr, status, e ); // If we have some XML response text (e.g. from an AJAX call) then log it in the console else if(xhr.responseText) console.log(xhr.responseText); }, createUploadIframe: function(id, uri) { //create frame var frameId = 'jUploadFrame' + id; var iframeHtml = '<iframe id="' + frameId + '" name="' + frameId + '" style="position:absolute; top:-9999px; left:-9999px"'; if(window.ActiveXObject) { if(typeof uri== 'boolean'){ iframeHtml += ' src="' + 'javascript:false' + '"'; } else if(typeof uri== 'string'){ iframeHtml += ' src="' + uri + '"'; } } iframeHtml += ' />'; jQuery(iframeHtml).appendTo(document.body); return jQuery('#' + frameId).get(0); }, createUploadForm: function(id, fileElementId, data) { //create form var formId = 'jUploadForm' + id; var fileId = 'jUploadFile' + id; var form = jQuery('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>'); if(data) { for(var i in data) { jQuery('<input type="hidden" name="' + i + '" value="' + data[i] + '" />').appendTo(form); } } var oldElement = jQuery('#' + fileElementId); var newElement = jQuery(oldElement).clone(); jQuery(oldElement).attr('id', fileId); jQuery(oldElement).before(newElement); jQuery(oldElement).appendTo(form); /*var oldElement = jQuery('#' + fileElementId); var newElement = oldElement.clone(true); newElement[0].files=oldElement[0].files; oldElement.attr('id', fileId); oldElement.before(newElement); 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 = new Date().getTime() var form = jQuery.createUploadForm(id, s.fileElementId, (typeof(s.data)=='undefined'?false:s.data)); var io = jQuery.createUploadIframe(id, s.secureuri); var frameId = 'jUploadFrame' + id; var formId = 'jUploadForm' + id; // Watch for a new set of requests if ( s.global && ! jQuery.active++ ) { jQuery.event.trigger( "ajaxStart" ); } var requestDone = false; // Create the request object var xml = {} if ( s.global ) jQuery.event.trigger("ajaxSend", [xml, s]); // Wait for a response to come back var uploadCallback = function(isTimeout) { 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; } //去掉html标签,以便返回的json能转换成对象 if(xml.responseText){ xml.responseText = xml.responseText.replace(/<pre[^>]*>|<\/pre>/g,''); } }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 a local callback was specified, fire it and pass it the data if ( s.success ) s.success( data, status ); // Fire the global callback if( s.global ) jQuery.event.trigger( "ajaxSuccess", [xml, s] ); } else jQuery.handleError(s, xml, status); } catch(e) { status = "error"; jQuery.handleError(s, xml, status, e); } // The request was completed if( s.global ) jQuery.event.trigger( "ajaxComplete", [xml, s] ); // Handle the global AJAX counter if ( s.global && ! --jQuery.active ) jQuery.event.trigger( "ajaxStop" ); // Process result 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(){ // Check to see if the request is still happening if( !requestDone ) 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) { jQuery(form).attr('encoding', 'multipart/form-data'); } else { jQuery(form).attr('enctype', 'multipart/form-data'); } jQuery(form).submit(); } catch(e) { jQuery.handleError(s, xml, null, e); } jQuery('#' + frameId).load(uploadCallback ); return {abort: function () {}}; }, uploadHttpData: function( r, type ) { var data = !type; data = type == "xml" || data ? r.responseXML : r.responseText; // If the type is "script", eval it in global context /* if ( type == "script" ) jQuery.globalEval( data ); // Get the JavaScript object, if JSON is used. if ( type == "json" ) eval( "data = " + data ); // evaluate scripts within html if ( type == "html" ) jQuery("<div>").html(data).evalScripts();*/ //修改原生js代码返回需要的图片上传key 去掉<script>标签内容 解决跨域问题 var reg=/<script[^>]*>.*(?=<\/script>)<\/script>/gi; data = data.replace(reg,''); return data; } })