SpringMVC中Ajax非同步上傳圖片的方法
專案中遇到了上傳圖片的需求,最開始用的是傳統的同步上傳,在需要上傳圖片的地方定義iframe,如下
<iframe id="uploadImg" frameborder=0 width=300 height=100 marginheight=0
marginwidth=0 scrolling=no src="jump_image_upload.xhtml">
</iframe>
這裡的src通過Controller將iframe內容扭轉至image_upload頁,再到該頁定義file控制元件進行圖片上傳。
這樣會帶來一個問題,即瀏覽器不相容,提交後的樣式在ie下面不可控,因此需要將同步上傳改為非同步上傳,上網找了一些外掛,最終發現ajaxfileupload.js比較好用,使用步驟如下:
1)下載ajaxfileupload.js,放到專案工程裡面,前端頁面使用如下:
$(".uploadBtn").click(function() {
$.ajaxFileUpload({
url : 'image_upload.json', //需要連結到伺服器地址
beforeSend:function(){$(".progress").show();},
secureuri : false,
fileElementId : 'uploadFile', //檔案選擇框的id屬性
dataType : 'json', //伺服器返回的格式,可以是json
success : function(data, status) //相當於java中try語句塊的用法
{
},
error : function(data, status, e) //相當於java中catch語句塊的用法
{
}
});
});
2)後臺程式碼如下:
@RequestMapping(value = "image_upload.json", method = RequestMethod.POST)
public void upload(@RequestParam(value="uploadFile")MultipartFile file,HttpServletRequest request,HttpServletResponse response) throws IOException
{
Map<String,String> model = new HashMap<String, String>();
String fileName = this.generateFileName(file.getOriginalFilename());
String path = request.getSession().getServletContext().getRealPath("upload");
File targetFile = this.imageUploadService.getTargetFile(path,fileName);
try
{
file.transferTo(targetFile);
this.imageUploadService.uploadImage(fileName, targetFile.getPath());
model.put("fileUrl", request.getContextPath() + "/upload/" + fileName);
model.put("file", fileName);
}
catch (Exception e)
{
logger.error("圖片上傳失敗!", e);
model.put("errorMsg", "圖片上傳失敗!");
}
JSONObject json = JSONObject.fromObject(model);
response.getWriter().write(json.toString());
response.getWriter().close();
}
最開始使用時,出現了一些問題,據說該外掛針對jquery1.7+版本支援不好,如下:
(1)控制檯提示少handerError方法;
具體解決方法是:上網找一個handlerError方法,新增到ajaxfileupload.js中。
(2)後臺上傳成功,但js總跳轉到error邏輯;
具體解決辦法:eval對data的處理有問題,將uploadHttpData方法中的eval( "data = " + $(data).html() ); 改為eval( "data = " + $(data).html() );
(3)IE瀏覽器下檔案上傳成功之後,總提示下載json資料
具體原因:針對非同步上傳檔案的請求,Controller後臺不能通過ResponseBody的方式返回json物件,而是要在後臺組裝成json資料格式,然後通過response物件write到前端頁面。
(4)IE和Firefox、chrome瀏覽器不相容
具體原因:response後臺在write出前端頁面的json資料時,不要設定contentType,之前我設定了:
response.setContentType("text/html;charset=UTF-8");
結果Firefox、chrome不正常,但IE正常;
後來設定了
response.setContentType("application/json;charset=UTF-8");
結果IE不正常,但Firefox、Chrome正常。
(5)檔案上傳一次之後,不重新整理頁面再次上傳同一個檔案,提示 上傳失敗
具體原因:檔案上傳時沒有重新命名,導致 file.transferTo(targetFile);這句出異常,每次上傳時將圖片按時間重新命名就ok了。
一個能夠正常執行的ajaxFileUpload.js全文如下:
jQuery.extend({
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] );
}
},
createUploadIframe: function(id, uri)
{
var frameId = 'jUploadFrame' + id;
if(window.ActiveXObject) {
if(jQuery.browser.version=="9.0")
{
io = document.createElement('iframe');
io.id = frameId;
io.name = frameId;
}
else if(jQuery.browser.version=="6.0" || jQuery.browser.version=="7.0" || jQuery.browser.version=="8.0")
{
var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
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;
},
ajaxUpload:function(s,xml){
//if((fromFiles.nodeType&&!((fileList=fromFiles.files)&&fileList[0].name)))
var uid = new Date().getTime(),idIO='jUploadFrame'+uid,_this=this;
var jIO=$('<iframe name="'+idIO+'" id="'+idIO+'" style="display:none">').appendTo('body');
var jForm=$('<form action="'+s.url+'" target="'+idIO+'" method="post" enctype="multipart/form-data"></form>').appendTo('body');
var oldElement = $('#'+s.fileElementId);
var newElement = $(oldElement).clone();
$(oldElement).attr('id', 'jUploadFile'+uid);
$(oldElement).before(newElement);
$(oldElement).appendTo(jForm);
this.remove=function()
{
if(_this!==null)
{
jNewFile.before(jOldFile).remove();
jIO.remove();jForm.remove();
_this=null;
}
}
this.onLoad=function(){
var data=$(jIO[0].contentWindow.document.body).text();
try{
if(data!=undefined){
data = eval('(' + data + ')');
try {
if (s.success)
s.success(data, status);
// Fire the global callback
if(s.global)
jQuery.event.trigger("ajaxSuccess", [xml, s]);
if (s.complete)
s.complete(data, status);
xml = null;
} 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
}
}catch(ex){
alert(ex.message);
};
}
this.start=function(){jForm.submit();jIO.load(_this.onLoad);};
return this;
},
createUploadForm: function(id, url,fileElementId, data)
{
//create form
var formId = 'jUploadForm' + id;
var fileId = 'jUploadFile' + id;
var form = jQuery('<form action="'+url+'" 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);
//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
// Create the request object
var xml = {};
s = jQuery.extend({}, jQuery.ajaxSettings, s);
if(window.ActiveXObject){
var upload = new jQuery.ajaxUpload(s,xml);
upload.start();
}else{
var id = new Date().getTime();
var form = jQuery.createUploadForm(id,s.url, 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;
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;
}
}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]);
if (s.complete)
s.complete(data, status);
} 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
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).html() );
}
// evaluate scripts within html
if ( type == "html" )
jQuery("<div>").html(data).evalScripts();
return data;
}
});
相關文章
- SpringMVC實現ajax上傳圖片實時預覽SpringMVC
- 基於SpringMVC的上傳圖片SpringMVC
- php 非同步上傳圖片幾種方法總結PHP非同步
- .Net 圖片縮圖上傳通用方法
- ci框架中的圖片上傳框架
- VueQuillEditor富文字上傳圖片-非base64VueUI
- 有道雲筆記非會員上傳圖片筆記
- SpringMVC之ajax非同步互動SpringMVC非同步
- 批次非同步上傳aws圖片指令碼(python)非同步指令碼Python
- laravel圖片/頭像上傳通用方法Laravel
- 上傳圖片
- PhpCms上傳圖片自動新增水印的方法教程PHP
- PbootCMS上傳圖片變模糊、上傳圖片尺寸受限的解決方案boot
- 織夢dedecms圖片集上傳圖片不能上傳 彈出提示302的解決方法
- electron上傳圖片
- 上傳圖片jsJS
- 裁剪上傳圖片
- 圖片上傳及圖片處理
- Typora中自定義命令上傳圖片
- [筆記]laravel的上傳檔案或者圖片的方法筆記Laravel
- topthink人物資訊中的封面圖片上傳。。。。
- java,springboot + thymeleaf 上傳圖片、刪除圖片到伺服器、本地,壓縮圖片上傳(有些圖片會失真),原圖上傳JavaSpring Boot伺服器
- js中圖片上傳,多次上傳同一張不生效JS
- H5 FileReader+drag+ajax2.0+Formdata實現圖片拖拽上傳H5ORM
- React圖片上傳元件react-fileupload的使用方法React元件
- layui中實現上傳圖片壓縮UI
- 多圖片formpost上傳ORM
- spring boot 圖片上傳Spring Boot
- 測試圖片上傳
- input file圖片上傳
- 本地Markdown上傳圖片
- 基於WebUploader的圖片上傳Web
- mino如何上傳同名的圖片
- AntD框架的upload元件上傳圖片時使用customRequest方法自定義上傳行為框架元件
- 上傳圖片 以及做成縮圖
- vue 上傳圖片進行壓縮圖片Vue
- Ueditor 上傳圖片自動新增水印(只能上傳圖片,上傳檔案報錯)
- Java實現圖片上傳到伺服器,並把上傳的圖片讀取出來Java伺服器
- SpringMvc上傳圖片及表單提交(單檔案+實體類引數提交)SpringMVC