spring mvc中引入xheditor的步骤(二)

用户发表文章(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>

最终的效果以下:

相关文章
相关标签/搜索