用戶發表文章(Post),在xheditor中寫文字和上傳圖片,交叉進行,圖片文件上傳到了服務器,圖片的名稱,url,大小等信息在上傳的同時須要單獨保存在一張表裏。 javascript
所以在上一篇的UploadController中除了作上傳圖片這事以外,還要向Attachment記錄圖片信息。修改代碼以下: css
@Controller @RequestMapping("/upload") public class UploadController { private static final Log logger = LogFactory.getLog(UploadController.class); @Autowired private AttachmentService attachmentService; @RequestMapping(value = "/image", method = RequestMethod.POST) @ResponseBody public String image(HttpServletRequest request, HttpSession session, @RequestParam("filedata") MultipartFile file) throws Exception { // 將圖片按日期分開存放,方便管理 final String prefix = "upload/images/" + DateUtil.getFormatedDate("yyyy/MM_dd"); // 存放到web根目錄下,若是日期目錄不存在,則建立, // 注意 request.getRealPath("/") 已經標記爲不推薦使用了. final String realPath = session.getServletContext().getRealPath(prefix); logger.info(realPath); File dir = new File(realPath); if (!dir.exists()) { dir.mkdirs(); } // 如下是真正的上傳部分 String error = ""; // 取得原文件名 String originName = file.getOriginalFilename(); // 取得文件後綴 String fileExt = originName.substring(originName.lastIndexOf(".") + 1); // 按時間戳生成圖片文件名 String picture = DateUtil.getFormatedDate("yyyyMMddHHmmss") + "." + fileExt; Attachment attachment = new Attachment(); try { IOUtils.copy(file.getInputStream(), new FileOutputStream(new File(dir, picture))); //向attachment表中插入一條post_id爲空的圖片記錄 attachment.setDownloadCount(0); attachment.setSize((int) file.getSize()); attachment.setUrl(prefix + "/" + picture); attachment = attachmentService.createAttachment(attachment); } catch (Exception e) { logger.error("error:", e); error = e.getMessage(); } String http = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); String url = http + "/" + prefix + "/" + picture; //注意這裏的格式(見xheditor文檔) //{'err':'',msg:{'url':'XXX/upload/images/2012/11_11/20121111015039.jpg','localname':'個人頭像.jpg','id':'63'}} String json = String.format("{'err':'%s',msg:{'url':'%s','localname':'%s','id':'%s'}}", error, url, originName, attachment.getId()); return json; } }
稍微解釋一下xheditor json字符串中幾個參數的做用:: html
(1)err:當這個值不爲空時,xheditor會在JSP中彈出一個上傳失敗的對話框並顯示err的內容
(2)url: 最終拼湊的可在瀏覽器中訪問的http圖片地址,xheditor直接根據這個值在editor中顯示圖片
(3)localname:這個值不是必須的,通常用來存儲圖片的名字,是url中的最後部分(也能夠不是,好比我url中的圖片名字是用時間戳命名的,而這裏localname是圖片自己的名字)
(4)id:這個值不是必須的,它表明圖片在attachment表中的id,回傳到JSP,當發表文章作進一步的處理 html5
這張表Attachment和Post是多對一關係,Attachment表中有一個post_id,問題是:保存圖片信息的時候, post_id還不存在(用戶尚未提交Post呢), java
怎麼辦呢? web
咱們能夠在每次上傳時插入一條沒有post_id的圖片記錄,等到用戶真正發表文章的時候,批量更新這些attachment的post_id,相關代碼以下: spring
@Override public void updateAttachmentsWithPostId(List<Attachment> attchments, Long postId) { List<Object[]> batchArgs = new ArrayList<Object[]>(); if (attchments != null) { for (Attachment attachment : attchments) { Object[] args = new Object[] { postId, attachment.getId() }; batchArgs.add(args); } } String sql = "update cms_attachment set post_id = ? where id=?"; jdbcTemplate.batchUpdate(sql, batchArgs); }
其間解決了一個@ResponseBody亂碼問題(json字符串中的localname爲中文時回傳到JSP中是亂碼)
在這裏找到了解決辦法:http://www.oschina.net/code/snippet_103691_11482,加入了以下配置: sql
<!-- 解決@ResponseBody亂碼問題, 須要在annotation-driven以前而且spring版本須要3.1.2以上 --> <!--Spring3.1推薦使用RequestMappingHandlerAdapter --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" /> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/plain;charset=UTF-8</value> </list> </property> </bean> <bean class="org.springframework.http.converter.ResourceHttpMessageConverter" /> <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" /> <bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter" /> <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter" /> </list> </property> </bean>
咱們能夠從spring日誌中看出加這個配置的做用 json
加以前 數組
[DEBUG] Written [{'err':'',msg:
{'url':'http://localhost:9080/spring/upload/images/2012/11_11/20121111011413.jpg','localname':'個人頭
像.jpg','id':'50'}}] as "text/html" using
[org.springframework.http.converter.StringHttpMessageConverter@93d9c7]
加以後:
[DEBUG] Written [{'err':'',msg:{'url':'http://localhost:9080/spring/upload/images/2012/11_11/20121111015039.jpg','localname':'個人頭像.jpg','id':'63'}}] as "text/plain;charset=UTF-8" using [org.springframework.http.converter.StringHttpMessageConverter@1fdec30]
前臺部分,相關的JS以下:
<script type="text/javascript"> //圖片預覽 function previewImage(x){ $('#preview').attr("src", "${ctx}/" + $(x).find("option:selected").val()); } $(document).ready(function() { //初始化xhEditor編輯器插件 $('#content').xheditor({ tools : 'full', skin : 'default', upImgUrl : "${ctx}/upload/image", upImgExt : "jpg,jpeg,png,gif", html5Upload : false, onUpload : insertUpload }); //圖片上傳回調函數 function insertUpload(arrMsg) { //xheditor返回的arrMsg是一個Object數組 var msg = arrMsg[0]; //(1)其中url插入到編輯器,這樣xheditor才能正常顯示圖片 var url = msg.url; $("#content").append(url); //如下步驟不是必須的 //(2)將attachment_id保存到checkbox中,發表文章時根據這些attachment_id去更新圖片的post_id var id = msg.id; $("#imagesDiv").append("<input type='checkbox' name='attachments' checked='checked' onclick='return false;' value='"+id+"''/><br>"); //(3)圖片的名字放到下拉列表,用戶從下拉列表 中選擇圖片作爲Post的主題圖片 var localname = msg.localname; var urlWithoutHttp = url.substring(url.indexOf("/upload")+1); $("#topicImageUrl").append("<option value='"+urlWithoutHttp+"'>" + localname + "</option>"); } //聚焦第一個輸入框 $("#name").focus(); //爲inputForm註冊validate函數 $("#inputForm").validate(); }); </script>
相關的form表單元素以下:
<div class="control-group"> <label class="control-label" for="content">內容:</label> <div class="controls"> <sf:textarea path="content" rows="15" cssClass="span10"/> </div> <div class="controls" id="imagesDiv" style="display:none"> </div> </div> <div class="control-group"> <label class="control-label" for="topicImageUrl">主題圖片:</label> <div class="controls"> <sf:select path="topicImageUrl" onchange='previewImage(this)'> <sf:option value="">Please select</sf:option> </sf:select> </div> </div> <div class="control-group"> <label class="control-label" for="hit">圖片預覽:</label> <div class="controls"> <img id="preview" src="" border="0" width="200" height="200" /> </div> </div>
最終的效果以下: