工做時遇到一個對輪播圖管理的需求,開發過程遇到些問題,總算順利解決,記錄下來供你們參考。原項目是基於SSM框架搭建的,現將Ajax圖片上傳部分分享以下:html
說明:ajax
1. 傳統的表單序列化,即經過$('#fm').serialize()能夠對form表單進行序列化,從而將form表單中的全部參數傳遞到服務端,但該方法只能傳遞通常的參數,上傳文件的文件流是沒法被序列化並傳遞的。json
2. 本文采起的方式是經過FormData對象實現的。現在主流瀏覽器都開始支持一個叫作FormData的對象,有了這個FormData,咱們就能夠輕鬆地使用Ajax方式進行文件上傳了。數組
FormData是什麼呢?
瀏覽器
XMLHttpRequest Level 2添加了一個新的接口FormData,利用
FormData對象,
咱們能夠經過JavaScript用一些鍵值對來模擬一系列表單控件,咱們還可使用XMLHttpRequest的Send()方法來異步的提交這個"表單"。比起普通的ajax,使用FormData
的最大優勢就是咱們能夠異步上傳一個二進制文件。全部主流瀏覽器的較新版本都已經支持這個對象了,好比Chrome 7+、Firefox 4+、IE 10+、Opera 12+、Safari 5+。
1.dao層代碼緩存
<!--新增照片 -->服務器
<insert id="addImage" parameterType="Image">app
<!--自動生成id(string類型) -->框架
<selectKey keyProperty="id" resultType="string" order="BEFORE">異步
SELECTUUID()
</selectKey>
insertinto image(id,imgName,path,uploadTime,uploader,type,displayOrder)
values(#{id},#{imgName},#{path},#{uploadTime},#{uploader},#{type},#{displayOrder})
</insert>
2.service層沒什麼邏輯,代碼在此省略
3.controller層代碼
@RequestMapping("/imageManage")
public class ImageController {
@Autowired
private ImageService imageService;
// 新增輪播圖片
@RequestMapping("/addImage")
@ResponseBody
public void addImg(
@RequestParam(value ="file", required =false) MultipartFile file,
@RequestParam(value ="uploader", required =false) String uploader,
HttpServletRequestrequest) {
String type =request.getParameter("type");
String order =request.getParameter("order");
Integer displayOrder =Integer.parseInt(order);
String DirectoryName ="/upload";
Image image =new Image();
if (uploader !=null) {
image.setUploader(uploader);
}
image.setUploadTime(DateUtil.DateToStr(DateUtil.yyyy_MM_dd_HH_mm_ss, new Date()));
image.setType(type);
//System.out.println("displayOrder"+ displayOrder.getClass().getName() + displayOrder);
String fileName =null;
if (file !=null) {
//取得當前上傳文件的文件名稱
String myFileName = file.getOriginalFilename();
//System.out.println("myfileName"+myFileName);
// System.out.println("文件名稱"+file.getContentType());
//若是名稱不爲"",說明該文件存在,不然說明該文件不存在
if (myFileName.trim() !="") {
//得到圖片的原始名稱
String originalFilename = file.getOriginalFilename();
//System.out.println("originalFilename----"+originalFilename);
//得到圖片後綴名稱,若是後綴不爲圖片格式,則不上傳
String suffix = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
//得到上傳路徑的絕對路徑地址(/upload)-->
String realPath = request.getSession().getServletContext().getRealPath("/" + DirectoryName);
// System.out.println(realPath);
//若是路徑不存在,則建立該路徑
File realPathDirectory =new File(realPath);
if (realPathDirectory ==null || !realPathDirectory.exists()) {
realPathDirectory.mkdirs();
}
//重命名上傳後的文件名 111112323.jpg
String format ="yyyyMMddHHmmss";
SimpleDateFormat simpleDateFormat =new SimpleDateFormat(format);
fileName= simpleDateFormat.format(new Date()) + suffix;
//定義上傳路徑 .../upload/111112323.jpg
File uploadFile =new File(realPathDirectory +"\\" + fileName);
// System.out.println(uploadFile);
image.setImgName(originalFilename);
//保存
try {
file.transferTo(uploadFile);
}catch (Exception e) {
e.printStackTrace();
}
image.setPath(request.getContextPath()+ DirectoryName +"\\" + fileName);
Image image_1 =new Image();
image_1.setType(type);
//根椐類型查詢
List<Image> list =imageService.getImageList(image_1);
if (list.size() != 0) {
//圖片是滿的就替換
if (list.size() == 4) {
for (Image image2 : list) {
if(image2.getDisplayOrder().equals(displayOrder)) {
imageService.delImage(image2);
}
}
image.setDisplayOrder(displayOrder);
imageService.addImage(image);
//圖片沒滿就日後推移
}else {
for (Image image2 : list) {
if(!image2.getDisplayOrder().equals(displayOrder)){
image.setDisplayOrder(displayOrder);
}else {
image.setDisplayOrder(list.size()+1);
}
}
imageService.addImage(image);
}
}else {
image.setDisplayOrder(1);
imageService.addImage(image);
}
}
}
}
4.HTML代碼
<div class="trd pic add">
<!-- enctype="multipart/form-data"是圖片上傳的基礎,必須有 -->
<form id="fm" name="fm" enctype="multipart/form-data" method="post">
<div class="namezone">輪播圖新增</div>
<div class="tablezoneclearfix">
<div class="left box">請添加圖片</div>
<div class="left box">
<div class="imageBoxclearfix">
<input type="file" class="file" name="file"/>
<span class="red">圖片需處理過</span>
</div>
</div>
<div class="left boxbtn">
展現順序
<select name="order" id="order">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<select name="type" id="type">
<option value="電腦">電腦</option>
<option value="手機">手機</option>
</select>
<input type="button" class="button" value="保存" id="save"/>
<input type="button" class="button" value="返回" id="back" onclick="history.go(-1)"/>
</div>
</div>
</form>
</div>
5.js代碼
var addPic = {
//點擊保存向後臺發送保存的數據
save :function (userName) {
$("#save").click(function () {
$.ajax({
type:"POST",
url:"/HuaMuWebsite/imageManage/addImage?uploader="+userName,
data:new FormData($("#fm")[0]),//序列化表單值
async:false,
contentType:false,//必須有
processData:false,//必須有
error:function(request) {
alert("請求出錯!");
},
success:function() {
$(window.parent.document).find("#iframe").attr("src",window.location.href="/HuaMuWebsite/admin/src/sliderCtrl.html?userName="+userName);
}
});
})
}
};
$(function () {
var userName=window.location.href;
var aa=userName.indexOf("=");
if( aa == -1)
return"";
userName=userName.substring(aa+1);
addPic.save(userName);
});
注意:contentType: false,
processData: false,
這兩個參數是必須的。兩者缺乏任何一個都會報錯。
ajax方法參數老是記不住,在此順便將ajax參數整理以下:
1)url: 要求爲String類型的參數,(默認爲當前頁地址)發送請求的地址。
2)type: 要求爲String類型的參數,請求方式(post或get)默認爲get。注意其餘http請求方法,例如put和delete也可使用,但僅部分瀏覽器支持。
3)async: 同步仍是異步,要求爲Boolean類型的參數,默認設置爲true,全部請求均爲異步請求。若是須要發送同步請求,請將此選項設置爲false。注意,同步請求將鎖住瀏覽器,用戶其餘操做必須等待請求完成才能夠執行。
4)cache: 要求爲Boolean類型的參數,默認爲true(當dataType爲script時,默認爲false),設置爲false將不會從瀏覽器緩存中加載請求信息。
5)data:要求爲Object或String類型的參數,要發送到服務器的數據。若是已經不是字符串,將自動轉換爲字符串格式。get請求中將附加在url後。防止這種自動轉換,能夠查看下邊的processData選項。對象必須爲key/value鍵值對格式,例如{key1:"value1",key2:"value2"}轉換爲&key1=value1&key2=value2。若是是數組,JQuery將自動爲不一樣值對應同一個名稱。例如{key:["value1","value2"]}轉換爲&key=value1&key=value2。
6)dataType: 要求爲String類型的參數,預期服務器返回的數據類型。若是不指定,JQuery將自動根據http包mime信息返回responseXML或responseText,並做爲回調函數參數傳遞。可用的類型以下:
xml:返回XML文檔,可用JQuery處理。
html:返回純文本HTML信息;包含的script標籤會在插入DOM時執行。
script:返回純文本JavaScript代碼。不會自動緩存結果。除非設置了cache參數。注意在遠程請求時(不在同一個域下),全部post請求都將轉爲get請求。
json:返回JSON數據。
jsonp:JSONP格式。使用JSONP形式調用函數時,例如myurl?callback=?,JQuery將自動替換後一個「?」爲正確的函數名,以執行回調函數。
text:返回純文本字符串。
7)success:要求爲Function類型的參數,請求成功後調用的回調函數,有兩個參數。
①由服務器返回,並根據dataType參數進行處理後的數據。
②描述狀態的字符串。
function(data, textStatus){
//data多是xmlDoc、jsonObj、html、text等等
this; //調用本次ajax請求時傳遞的options參數
}
8)error:要求爲Function類型的參數,請求失敗時被調用的函數。該函數有3個參數,即XMLHttpRequest對象、錯誤信息、捕獲的錯誤對象(可選)。ajax事件函數以下:
function(XMLHttpRequest,textStatus, errorThrown){
//一般狀況下textStatus和errorThrown只有其中一個包含信息
this; //調用本次ajax請求時傳遞的options參數
}
9)contentType:要求爲Boolean類型的參數,當發送信息至服務器時,內容編碼類型默認爲"application/x-www-form-urlencoded"。該默認值適合大多數應用場合。
10)processData:要求爲Boolean類型的參數,默認爲true。默認狀況下,發送的數據將被轉換爲對象(從技術角度來說並不是字符串)以配合默認內容類型"application/x-www-form-urlencoded"。若是要發送DOM樹信息或者其餘不但願轉換的信息,請設置爲false。
11)jsonp:要求爲String類型的參數,在一個jsonp請求中重寫回調函數的名字。該值用來替代在"callback=?"這種GET或POST請求中URL參數裏的"callback"部分,例如{jsonp:'onJsonPLoad'}會致使將"onJsonPLoad=?"傳給服務器。
12)username:要求爲String類型的參數,用於響應HTTP訪問認證請求的用戶名。
13)password:要求爲String類型的參數,用於響應HTTP訪問認證請求的密碼。
14)ifModified:要求爲Boolean類型的參數,默認爲false。僅在服務器數據改變時獲取新數據。服務器數據改變判斷的依據是Last-Modified頭信息。默認值是false,即忽略頭信息。
15)scriptCharset:要求爲String類型的參數,只有當請求時dataType爲"jsonp"或者"script",而且type是GET時纔會用於強制修改字符集(charset)。一般在本地和遠程的內容編碼不一樣時使用。
16)dataFilter:要求爲Function類型的參數,給Ajax返回的原始數據進行預處理的函數。提供data和type兩個參數。data是Ajax返回的原始數據,type是調用jQuery.ajax時提供的dataType參數。函數返回的值將由jQuery進一步處理。
function(data, type){
//返回處理後的數據
return data;
}
17)timeout: 要求爲Number類型的參數,設置請求超時時間(毫秒)。此設置將覆蓋$.ajaxSetup()方法的全局設置。
18)global:要求爲Boolean類型的參數,默認爲true。表示是否觸發全局ajax事件。設置爲false將不會觸發全局ajax事件,ajaxStart或ajaxStop可用於控制各類ajax事件。
19)beforeSend:要求爲Function類型的參數,發送請求前能夠修改XMLHttpRequest對象的函數,例如添加自定義HTTP頭。在beforeSend中若是返回false能夠取消本次ajax請求。XMLHttpRequest對象是唯一的參數。
function(XMLHttpRequest){
this; //調用本次ajax請求時傳遞的options參數
}
20)complete:要求爲Function類型的參數,請求完成後調用的回調函數(請求成功或失敗時均調用)。參數:XMLHttpRequest對象和一個描述成功請求類型的字符串。
function(XMLHttpRequest, textStatus){
this; //調用本次ajax請求時傳遞的options參數 }