Spring MVC 實現文件上傳
時序圖
利用 Spring MVC 實現文件上傳功能,離不開對 MultipartResolver 的設置。MultipartResolver 這個類,你可以將其視為 Spring MVC 實現文件上傳功能時的工具類,這個類也只會在文件上傳中發揮作用。在配置了具體實現類之后,Spring MVC 中的 DispatcherServlet 在處理請求時會調用 MultipartResolver 中的方法判斷此請求是不是文件上傳請求。如果是,DispatcherServlet 將調用 MultipartResolver 的 resolveMultipart(request) 方法對該請求對象進行裝飾並返回一個新的 MultipartHttpServletRequest 供后繼處理流程使用。注意,此時的請求對象會由 HttpServletRequest 類型轉換成 MultipartHttpServletRequest 類型,這個類中會包含所上傳的文件對象,可供后續流程直接使用,而無需自行在代碼中實現對文件內容的讀取邏輯。
當收到請求時,DispatcherServlet 的 checkMultipart() 方法會調用 MultipartResolver 的 isMultipart() 方法判斷請求中是否包含文件。
如果請求數據中包含文件,則調用 MultipartResolver 的 resolveMultipart() 方法對請求的數據進行解析,然后將文件數據解析成 MultipartFile 並封裝在 MultipartHttpServletRequest(繼承了 HttpServletRequest)對象中,最后傳遞給 Controller 控制器。
圖片上傳實現
實現文件上傳時需要依賴相關 Jar 包,我們首先在 pom 文件中將依賴包添加進來:
-
pom.xml 。
<!-- Start: commons相關依賴包 --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>${commons-io.version}</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>${commons-fileupload.version}</version> </dependency> <!-- Start: commons相關依賴包 -->
-
spring-mvc.xml
-
如下設置 MultipartResolver,我們使用的是仍是 CommonsMultipartResolver 實現類:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 設定默認編碼 --> <property name="defaultEncoding" value="UTF-8"></property> <!-- 設定文件上傳的最大值為5MB,5*1024*1024 --> <property name="maxUploadSize" value="5242880"></property> </bean>
-
LoadImageController.java 。
通過前文中的分析,可知文件對象已被封裝到 MultipartFile 對象中,在代碼中可以直接使用此文件對象,之后調用 File 相關方法將文件存儲到 upload 目錄下,代碼如下:
public Result upload(HttpServletRequest request, @RequestParam("file") MultipartFile file) throws IOException { ServletContext sc = request.getSession().getServletContext(); String dir = sc.getRealPath("/upload"); String type = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1, file.getOriginalFilename().length()); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss"); Random r = new Random(); String imgName = ""; if ("jpg".equals(type)) { imgName = sdf.format(new Date()) + r.nextInt(100) + ".jpg"; } else if ("png".equals(type)) { imgName = sdf.format(new Date()) + r.nextInt(100) + ".png"; } else if ("jpeg".equals(type)) { imgName = sdf.format(new Date()) + r.nextInt(100) + ".jpeg"; } else if ("gif".equals(type)) { imgName = sdf.format(new Date()) + r.nextInt(100) + ".gif"; } else { return null; } //將文件流寫入到磁盤中 FileUtils.writeByteArrayToFile(new File(dir, imgName), file.getBytes()); //返回文件路徑 return Result.ok().put("url", "/upload/" + imgName); }
這樣圖片上傳至本地的過程就完成了
實現圖片管理模塊
流程設計
圖片管理模塊主要包括列表,添加,編輯,刪除功能。
列表功能的實現流程。這里我們選用JqGrid作為分頁的功能插件。
添加功能的具體過程為:點擊“添加”按鈕 - >選擇圖片並上傳 - >填寫備注信息 - >保存至數據庫。
修改編輯功能的流程圖與添加功能類似,唯一的區別是點擊修改按鈕前需要把對應的預覽圖和備注從數據庫獲取並展示在修改界面,讓用戶知道修改的是哪個圖片。
刪除功能基本流程為,在數據列表區選擇想要刪除的數據,之后點擊“刪除”按鈕,觸發刪除()事件並向后端發送刪除請求,成功后重新刷新列表數據。
頁面與交互
圖片模塊頁面構成主要為主頁面和信息編輯彈框。
功能划分
主頁面的設計效果圖,如下所示:
如上圖所示,圖片模塊頁面的布局組成為:模塊標題區域,模塊功能區域。
其中,模塊功能區又包含功能按鈕區域,列表信息區域和分頁信息區域。
信息編輯彈框設計效果圖,如下所示:
由上圖可知,信息編輯彈框區域的組成為:
- 標題區域; - 錯誤提示區域; - 圖片預覽區域; - 上傳按鈕; - 信息輸入區; - 表單提交區域。
操作
主頁面包括如下操作:
- 按鈕點擊; - 記錄選擇; - 翻頁。
添加/修改按鈕點擊后會出現信息編輯彈框,此時又會產生如下操作:
- 文件上傳; - 信息輸入; - 請求提交。
反饋效果
接下來,我們看下圖片模塊包含哪些交互,交互過程是怎樣的。
- 列表數據重新加載:頁面初始化時或者點擊分頁按鈕時,JqGrid會對列表數據進行渲染及重新渲染。
- 彈框:點擊“添加”或者“修改”按鈕后會顯示信息編輯彈框。
- 選中提示:點擊“編輯”按鈕前,如果未選中一條編輯記錄或者選中了多條編輯記錄,都會彈出此提示。點擊刪除按鈕前,如果未選中記錄也會出現此提示。
- 錯誤提示區顯示:用戶信息輸入不規范會看到此錯誤提示。
- 請求處理完成提示:添加請求,修改請求,刪除請求完成后會出現此提示。
- 頁面跳轉。頁面跳轉方向主要有:
跳入:點擊導航欄的“圖片管理”會進入此頁面。無操作:未點擊功能按鈕或者輸入信息錯誤則不跳轉。跳出:身份認證失敗會進入登錄頁面。
前端實現
前端頁面代碼文件,我們命名為picture.html
初始化上傳者
前端的文件上傳插件,我們使用的是JQuery的ajaxupload工具。接下來,帶大家了解如何在前端頁面中使用它。
首先,在頁面中引入依賴文件:
<!-- ajax upload --> <script src="plugins/ajaxupload/ajaxupload.js"></script>
然后,設置上傳按鈕DOM對象:
<div class="col-sm-10"> <a class="btn btn-info" id="upload"><i class="fa fa-picture-o"></i> 上傳文件</a> </div>
上傳代碼邏輯如下,首先判斷文件格式,圖片上傳限制文件格式為jpg,png,gif,其他格式的文件將不會被處理,之后向后端發送文件上傳請求,並根據后端返回數據進行相應的事件處理。
1 new AjaxUpload('#upload', { 2 action: 'images', 3 name: 'file', 4 autoSubmit: true, 5 responseType: "json", 6 onSubmit: function (file, extension) { 7 if (!(extension && /^(jpg|jpeg|png|gif)$/.test(extension.toLowerCase()))) { 8 alert('只支持jpg、png、gif格式的圖片!', { 9 icon: "error", 10 }); 11 return false; 12 } 13 }, 14 onComplete: function (file, r) { 15 if (r.resultCode == 200) { 16 alert("上傳成功"); 17 $("#picturePath").val(r.data); 18 $("#img").attr("src", r.data); 19 $("#img").attr("style", "width: 100px;height: 100px;display:block;"); 20 return false; 21 } else { 22 alert(r.message); 23 } 24 } 25 });
以下通過注釋對ajaxupload插件初始化時的主要參數均做了說明:
new AjaxUpload('#upload', {//上傳按鈕DOM //文件上傳后台處理url action: 'images', //參數名稱,對應的是Controller中的 @RequestParam("file") MultipartFile file,如果兩個名稱不同則會報錯 name: 'file', //是否自動提交 autoSubmit: true, //服務器返回的數據類型 responseType: "json", //請求提交前執行的函數 onSubmit: function (file, extension) { }, //請求完成后的回調函數 onComplete: function (file, r) { } });
功能代碼
在信息編輯彈框頁面中,當文件上傳完成,備注信息輸入完成后點擊“確認”按鈕,首先會執行validObject()方法校驗輸入參數,校驗邏輯通過后則進行數據封裝,並發送網絡請求至后端。之后根據后端返回的結果對象進行對應的操作,如果出現報錯則直接提醒用戶錯誤信息,如果后端返回成功則根據不同的resultCode進行對應的操作.resultCode等於200,則表示請求成功,關閉彈框,提示用戶保存成功並重新加載圖片信息列表數據.
1 $('#saveButton').click(function () { 2 //驗證數據 3 if (validObject()) { 4 //一切正常后發送網絡請求 5 //ajax 6 var id = $("#pictureId").val(); 7 var picturePath = $("#picturePath").val(); 8 var pictureRemark = $("#pictureRemark").val(); 9 var data = {"path": picturePath, "remark": pictureRemark}; 10 $.ajax({ 11 type: 'POST',//方法類型 12 dataType: "json",//預期服務器返回的數據類型 13 url: pictures/save,//url 14 contentType: "application/json; charset=utf-8", 15 beforeSend: function (request) { 16 //設置header值 17 request.setRequestHeader("token", getCookie("token")); 18 }, 19 data: JSON.stringify(data), 20 success: function (result) { 21 checkResultCode(result.resultCode); 22 if (result.resultCode == 200) { 23 $('#pictureModal').modal('hide'); 24 alert("保存成功"); 25 reload(); 26 } else { 27 $('#pictureModal').modal('hide'); 28 alert("保存失敗"); 29 }; 30 } 31 }); 32 33 } 34 });
后端實現
表結構設計
新增tb ssm圖片用來存儲圖片信息,建表語句如下:
use gitchat_ssm_demo_db; DROP TABLE IF EXISTS `tb_ssm_picture`; CREATE TABLE `tb_ssm_picture` ( `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `path` varchar(200) NOT NULL DEFAULT '' COMMENT '圖片路徑', `remark` varchar(200) NOT NULL DEFAULT '' COMMENT '備注', `is_deleted` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否已刪除 0未刪除 1已刪除', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '添加時間', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DAO層
1 <select id="findPictures" parameterType="Map" resultMap="PictureResult"> 2 select id,path,remark,create_time from tb_ssm_picture 3 where is_deleted=0 4 order by id desc 5 <if test="start!=null and limit!=null"> 6 limit #{start},#{limit} 7 </if> 8 </select> 9 10 <select id="getTotalPictures" parameterType="Map" resultType="int"> 11 select count(*) from tb_ssm_picture 12 where is_deleted=0 13 </select> 14 15 <insert id="insertPicture" parameterType="com.ssm.demo.entity.Picture"> 16 insert into tb_ssm_picture(path,remark) 17 values(#{path},#{remark}) 18 </insert> 19 20 <update id="updPicture" parameterType="com.ssm.demo.entity.Picture"> 21 update tb_ssm_picture 22 set 23 path=#{path},remark=#{remark} 24 where id=#{id} and is_deleted=0 25 </update> 26 27 <update id="delPicture" parameterType="int"> 28 update tb_ssm_picture 29 set is_deleted=1 where id=#{id} 30 </update> 31 32 <select id="findPictureById" parameterType="int" resultMap="PictureResult"> 33 select id,path,remark,create_time 34 from tb_ssm_picture where id=#{id} and is_deleted=0 35 </select> 36 37 //刪除功能是使用的邏輯刪除 38 <update id="deleteBatch"> 39 update tb_ssm_picture 40 set is_deleted=1 where id in 41 <foreach item="id" collection="array" open="(" separator="," close=")"> 42 #{id} 43 </foreach> 44 </update>
Service 層
新增業務層代碼方法 getPicturePage() 、 save() 、 update() 、 deleteBatch ,分別對應圖片信息的分頁查詢、新增功能、修改功能和刪除功能。業務代碼的具體實現邏輯為調用 DAO 層中的方法對 MySQL 進行數據查詢及數據更改。
@Override public PageResult getPicturePage(PageUtil pageUtil) { List<Picture> pictures = pictureDao.findPictures(pageUtil); int total = pictureDao.getTotalPictures(pageUtil); PageResult pageResult = new PageResult(pictures, total, pageUtil.getLimit(), pageUtil.getPage()); return pageResult; } @Override public Picture queryObject(Integer id) { return pictureDao.findPictureById(id); } @Override public int save(Picture picture) { return pictureDao.insertPicture(picture); } @Override public int update(Picture picture) { return pictureDao.updPicture(picture); } @Override public int delete(Integer id) { return pictureDao.delPicture(id); } @Override public int deleteBatch(Integer[] ids) { return pictureDao.deleteBatch(ids); }
Controller 層
控制層代碼邏輯主要為參數校驗、請求校驗,對前端提交的請求進行路由和方法實現,之后根據方法返回封裝 Result 對象並返回至前端,以下為圖片信息管理功能模塊所有方法的實現代碼:
1 /** 2 * 列表 3 */ 4 @RequestMapping("/list") 5 public Result list(@RequestParam Map<String, Object> params) { 6 if (StringUtils.isEmpty(params.get("page")) || StringUtils.isEmpty(params.get("limit"))) { 7 return ResultGenerator.genErrorResult(Constants.RESULT_CODE_PARAM_ERROR, "參數異常!"); 8 } 9 //查詢列表數據 10 PageUtil pageUtil = new PageUtil(params); 11 return ResultGenerator.genSuccessResult(pictureService.getPicturePage(pageUtil)); 12 } 13 14 /** 15 * 信息 16 */ 17 @RequestMapping("/info/{id}") 18 public Result info(@PathVariable("id") Integer id, @TokenToUser AdminUser loginUser) { 19 if (loginUser == null) { 20 return ResultGenerator.genErrorResult(Constants.RESULT_CODE_NOT_LOGIN, "未登錄!"); 21 } 22 if (id < 1) { 23 return ResultGenerator.genErrorResult(Constants.RESULT_CODE_PARAM_ERROR, "參數異常!"); 24 } 25 Picture picture = pictureService.queryObject(id); 26 if (picture == null) { 27 return ResultGenerator.genErrorResult(Constants.RESULT_CODE_PARAM_ERROR, "參數異常!"); 28 } 29 return ResultGenerator.genSuccessResult(picture); 30 } 31 32 /** 33 * 保存 34 */ 35 @RequestMapping("/save") 36 public Result save(@RequestBody Picture picture, @TokenToUser AdminUser loginUser) { 37 if (loginUser == null) { 38 return ResultGenerator.genErrorResult(Constants.RESULT_CODE_NOT_LOGIN, "未登錄!"); 39 } 40 if (StringUtils.isEmpty(picture.getPath()) || StringUtils.isEmpty(picture.getRemark())) { 41 return ResultGenerator.genErrorResult(Constants.RESULT_CODE_PARAM_ERROR, "參數異常!"); 42 } 43 if (pictureService.save(picture) > 0) { 44 return ResultGenerator.genSuccessResult(); 45 } else { 46 return ResultGenerator.genFailResult("添加失敗"); 47 } 48 } 49 50 /** 51 * 修改 52 */ 53 @RequestMapping("/update") 54 public Result update(@RequestBody Picture picture, @TokenToUser AdminUser loginUser) { 55 if (loginUser == null) { 56 return ResultGenerator.genErrorResult(Constants.RESULT_CODE_NOT_LOGIN, "未登錄!"); 57 } 58 if (null == picture.getId() || StringUtils.isEmpty(picture.getPath()) || StringUtils.isEmpty(picture.getRemark())) { 59 return ResultGenerator.genErrorResult(Constants.RESULT_CODE_PARAM_ERROR, "參數異常!"); 60 } 61 Picture tempPicture = pictureService.queryObject(picture.getId()); 62 if (tempPicture == null) { 63 return ResultGenerator.genErrorResult(Constants.RESULT_CODE_PARAM_ERROR, "參數異常!"); 64 } 65 if (pictureService.update(picture) > 0) { 66 return ResultGenerator.genSuccessResult(); 67 } else { 68 return ResultGenerator.genFailResult("修改失敗"); 69 } 70 } 71 72 /** 73 * 刪除 74 */ 75 @RequestMapping("/delete") 76 public Result delete(@RequestBody Integer[] ids, @TokenToUser AdminUser loginUser) { 77 if (loginUser == null) { 78 return ResultGenerator.genErrorResult(Constants.RESULT_CODE_NOT_LOGIN, "未登錄!"); 79 } 80 if (ids.length < 1) { 81 return ResultGenerator.genErrorResult(Constants.RESULT_CODE_PARAM_ERROR, "參數異常!"); 82 } 83 if (pictureService.deleteBatch(ids) > 0) { 84 return ResultGenerator.genSuccessResult(); 85 } else { 86 return ResultGenerator.genFailResult("刪除失敗"); 87 } 88 }
刪除功能
刪除功能通常分為邏輯刪除和物理刪除,邏輯刪除是名義上的刪除,而物理刪除是真正的刪除。
舉個簡單的例子,倉庫的貨架上堆放着各種商品,管理員在取商品的時候不是直接去貨架找,而是通過貨架商品單上記錄的信息去找,按照單子上面記載的位置再去找商品。邏輯刪除相當於把貨架商品單上的記錄用線划掉,表明這件商品已經賣出去了或者已經處理掉了,可實際上物品並沒有被拿走還是放在庫里,只不過是被標記為 “ 已處理 ” 即不能再進行出庫操作了。而物理刪除則是把倉庫貨架上的商品實實在在扔掉或者處理掉了,即貨架中根本沒有這件商品了。
兩者在編碼實現時的區別是使用 delete 語句還是 update 語句。
比如,物理刪除的實現代碼為:
delete from tb_xxx where id = 10
而邏輯刪除的實現代碼為:
update tb_xxx set is_deleted=1 where id = 10
在實際開發過程中,刪除數據一定要慎重,對於重要的數據,最好不要輕易物理刪除(即直接刪除),在必要的情況下可以使用邏輯刪除的方法,即設置一個刪除標志的列屬性表示邏輯刪除,比如本項目中使用的就是 is_deleted 字段來標識記錄是否被刪除。
具體的js代碼
1 $(function () { 2 //隱藏彈框 3 $('#pictureModal').modal('hide'); 4 //隱藏錯誤提示框 5 $('.alert-danger').css("display", "none"); 6 7 //modal綁定hide事件 8 $('#pictureModal').on('hide.bs.modal', function () { 9 reset(); 10 }); 11 $("#jqGrid").jqGrid({ 12 url: 'pictures/list', 13 datatype: "json", 14 colModel: [ 15 {label: 'id', name: 'id', index: 'id', width: 50, sortable: false, hidden: true, key: true}, 16 {label: '圖片預覽', name: 'path', index: 'path', sortable: false, width: 105, formatter: imgFormatter}, 17 {label: '圖片備注', name: 'remark', index: 'remark', sortable: false, width: 105}, 18 {label: '添加時間', name: 'createTime', index: 'createTime', sortable: true, width: 80} 19 ], 20 height: 385, 21 rowNum: 10, 22 rowList: [10, 30, 50], 23 styleUI: 'Bootstrap', 24 loadtext: '信息讀取中...', 25 rownumbers: true, 26 rownumWidth: 25, 27 autowidth: true, 28 multiselect: true, 29 pager: "#jqGridPager", 30 jsonReader: { 31 root: "data.list", 32 page: "data.currPage", 33 total: "data.totalPage", 34 records: "data.totalCount" 35 }, 36 prmNames: { 37 page: "page", 38 rows: "limit", 39 order: "order" 40 }, 41 gridComplete: function () { 42 //隱藏grid底部滾動條 43 $("#jqGrid").closest(".ui-jqgrid-bdiv").css({"overflow-x": "hidden"}); 44 } 45 }); 46 47 //預覽圖的設置 48 function imgFormatter(cellvalue) { 49 return "<a href='" + cellvalue + "'> <img src='" + cellvalue + "' height=\"120\" width=\"135\" alt='SSM'/></a>"; 50 } 51 52 // 上傳前的預覽圖展示和上傳照片步驟 53 new AjaxUpload('#upload', { 54 action: 'images', 55 name: 'file', 56 autoSubmit: true, 57 responseType: "json", 58 onSubmit: function (file, extension) { 59 if (!(extension && /^(jpg|jpeg|png|gif)$/.test(extension.toLowerCase()))) { 60 alert('只支持jpg、png、gif格式的圖片!', { 61 icon: "error", 62 }); 63 return false; 64 } 65 }, 66 onComplete: function (file, r) { 67 if (r.resultCode == 200) { 68 alert("上傳成功"); 69 $("#picturePath").val(r.data); 70 $("#img").attr("src", r.data); 71 console.log("r.data="+r.data); 72 $("#img").attr("style", "width: 100px;height: 100px;display:block;"); 73 return false; 74 } else { 75 alert(r.message); 76 } 77 } 78 }); 79 }); 80 81 //綁定modal上的保存按鈕 82 $('#saveButton').click(function () { 83 //驗證數據 84 if (validObject()) { 85 //一切正常后發送網絡請求 86 //ajax 87 var id = $("#pictureId").val(); 88 var picturePath = $("#picturePath").val(); 89 var pictureRemark = $("#pictureRemark").val(); 90 var data = {"path": picturePath, "remark": pictureRemark}; 91 var url = 'pictures/save'; 92 //id>0表示編輯操作 93 if (id > 0) { 94 data = {"id": id, "path": picturePath, "remark": pictureRemark}; 95 url = 'pictures/update'; 96 } 97 $.ajax({ 98 type: 'POST',//方法類型 99 dataType: "json",//預期服務器返回的數據類型 100 url: url,//url 101 contentType: "application/json; charset=utf-8", 102 beforeSend: function (request) { 103 //設置header值 104 request.setRequestHeader("token", getCookie("token")); 105 }, 106 data: JSON.stringify(data), 107 success: function (result) { 108 checkResultCode(result.resultCode); 109 if (result.resultCode == 200) { 110 $('#pictureModal').modal('hide'); 111 alert("保存成功"); 112 reload(); 113 } 114 else { 115 $('#pictureModal').modal('hide'); 116 alert("保存失敗"); 117 } 118 ; 119 }, 120 error: function () { 121 alert("操作失敗"); 122 } 123 }); 124 } 125 }); 126 127 function pictureAdd() { 128 reset(); 129 $('.modal-title').html('圖片添加'); 130 $('#pictureModal').modal('show'); 131 } 132 133 function pictureEdit() { 134 reset(); 135 $('.modal-title').html('修改圖片'); 136 137 var id = getSelectedRow(); 138 if (id == null) { 139 return; 140 } 141 //請求數據 142 $.ajax({ 143 type: "GET", 144 url: "pictures/info/" + id, 145 contentType: "application/json", 146 beforeSend: function (request) { 147 //設置header值 148 request.setRequestHeader("token", getCookie("token")); 149 }, 150 success: function (r) { 151 checkResultCode(r.resultCode); 152 if (r.resultCode == 200 && r.data != null) { 153 //填充數據至modal 154 console.log(r.data); 155 $('#pictureId').val(r.data.id); 156 $("#img").attr("src", r.data.path); 157 $("#img").attr("style", "width: 100px;height: 100px;display:block;"); 158 $('#picturePath').val(r.data.path); 159 $('#pictureRemark').val(r.data.remark); 160 } 161 } 162 }); 163 //顯示modal 164 $('#pictureModal').modal('show'); 165 } 166 167 /** 168 * 數據驗證 169 */ 170 function validObject() { 171 var picturePath = $('#picturePath').val(); 172 if (isNull(picturePath)) { 173 showErrorInfo("圖片不能為空!"); 174 return false; 175 } 176 var pictureRemark = $('#pictureRemark').val(); 177 if (isNull(pictureRemark)) { 178 showErrorInfo("備注信息不能為空!"); 179 return false; 180 } 181 if (!validLength(pictureRemark, 150)) { 182 showErrorInfo("備注信息長度不能大於150!"); 183 return false; 184 } 185 if (!validLength(picturePath, 120)) { 186 showErrorInfo("圖片上傳有誤!"); 187 return false; 188 } 189 return true; 190 } 191 192 /** 193 * 重置 194 */ 195 function reset() { 196 //隱藏錯誤提示框 197 $('.alert-danger').css("display", "none"); 198 //清空數據 199 $('#pictureId').val(0); 200 $('#picturePath').val(''); 201 $('#pictureRemark').val(''); 202 $("#img").attr("style", "display:none;"); 203 } 204 205 function deletePicture() { 206 var ids = getSelectedRows(); 207 if (ids == null) { 208 return; 209 } 210 $.ajax({ 211 type: "POST", 212 url: "pictures/delete", 213 contentType: "application/json", 214 beforeSend: function (request) { 215 //設置header值 216 request.setRequestHeader("token", getCookie("token")); 217 }, 218 data: JSON.stringify(ids), 219 success: function (r) { 220 checkResultCode(r.resultCode); 221 if (r.resultCode == 200) { 222 alert("刪除成功"); 223 $("#jqGrid").trigger("reloadGrid"); 224 } else { 225 alert(r.message); 226 } 227 } 228 }); 229 } 230 231 /** 232 * jqGrid重新加載 233 */ 234 function reload() { 235 reset(); 236 var page = $("#jqGrid").jqGrid('getGridParam', 'page'); 237 $("#jqGrid").jqGrid('setGridParam', { 238 page: page 239 }).trigger("reloadGrid"); 240 }