使用FormData进行Ajax请求异步上传图片案例
2019獨角獸企業重金招聘Python工程師標準>>>
工作時遇到一個對輪播圖管理的需求,開發過程遇到些問題,總算順利解決,記錄下來供大家參考。原項目是基于SSM框架搭建的,現將Ajax圖片上傳部分分享如下:
說明:
1. 傳統的表單序列化,即通過$('#fm').serialize()可以對form表單進行序列化,從而將form表單中的所有參數傳遞到服務端,但該方法只能傳遞一般的參數,上傳文件的文件流是無法被序列化并傳遞的。
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">
?????????????<!--自動生成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層代碼
@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參數
????????? }
轉載于:https://my.oschina.net/u/3676262/blog/1552890
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的使用FormData进行Ajax请求异步上传图片案例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】用 PHP V5 开发多任务应用程
- 下一篇: C++运算符重载(10)