文件的上传和下载功能

这里仅仅介绍JeeCMS中文件上传和下载功能。从前台到后台分析,希望笔者对该功能也能有更多的理解,温故知新。

html代码:

<table id="attachTable" border="0">
<tr>
	<td align="center">
	        
	</td>
	<td align="center">
		附件名称
	</td>
	<td align="center">
		上传
	</td>
</tr>
<tr id="attachTr${a_index}">
	<td align="center">
		<a οnclick="$('#attachTr${a_index}').remove();" href="javascript:void(0);" class="pn-opt">删除</a>
	</td>
	<td align="center">
		<input type="text" id="attachmentNames${a_index}" value="${a.name}" name="attachmentNames"/>
		<input type="hidden" id="attachmentPaths${a_index}" value="${a.path}" name="attachmentPaths"/>
	</td>
	<td align="center">
		<span id="afc${a_index}" style="position:relative;display:block;width:300px;*width:300px;">
		<input type='text' class="text_size" id='attachmentText${a_index}'/>
		<input class="browse" type='button' value='浏览'/>
		<input οnchange="$('#attachmentText${a_index}').val(this.value)" size="19" type="file" name="attachmentFile" id="attachmentFile${a_index}" style="height:24px;opacity:0;filter:alpha(opacity=0);position:absolute;right:69px;top:2px;"/>
		<input type="button" value="上传" οnclick="uploadAttachment(${a_index});" class="upload-button"/>
		</span>
		<input type="hidden" id="attachmentFilenames${a_index}" name="attachmentFilenames"/>
	</td>
</tr>
</table>

这里最主要的有三个字段,attachmentNames,attachmentPath,attachmentFilenames这是三个要存进数据库的字段,在上传的同时要把这三个字段填充完整。以便在提交时可以在后台取到。

上传文件的大致流程:点击浏览选取文件-->点击上传-->js函数触发获得各个参数和File-->后台读取文件上传到指定目录-->返回到前台参数-->提交至数据库。

其中比较重要两个点就是,js函数和后台读取文件的过程。下面将进行重点说明:

function uploadAttachment(n) {
	var af = $('#attachmentFile'+n);
	//检查是否选择了文件
	if(af.val()=='') {
		alert('没有选择文件!');
		return;
	}
	//将file移动至上传表单
	$('#attachmentContent').empty();
	$('#attachmentContent').append(af);
	//复制一个file放至原处
	//dump_obj(af);
	//dump_obj(attachmentContent);
	$('#afc'+n).append(af.clone().attr('value',''));
	$('#attachmentText'+n).attr('value','');
	//修改属性
	af.attr('id','');
	af.attr('name','attachmentFile');
	//其他表单
	var attachmentForm = document.getElementById('attachmentForm');
	$('#attachmentNum').val(n);
	$('#attachmentForm').submit();
}

<form id="attachmentForm" action="o_upload_attachment.jspx" method="post" enctype="multipart/form-data" target="attachment_iframe" style="display:none;width:0px;height:0px;">
<span id="attachmentContent"></span>
<input type="hidden" id="attachmentNum" name="attachmentNum"/>
</form>
<iframe name="attachment_iframe" frameborder="0" border="0" style="display:none;width:0px;height:0px;"></iframe>
这里js函数的几个部分:1,监测是否选取文件;2,将file文件放到表单attachmentForm中;3,获取其他参数(filename,num,file)并提交至后台。

这里需要注意:

enctype="multipart/form-data"
这个属性是必需的,在上传文件的时候需要以字节流的形式上传,这个属性也必须加上。另外iframe是用来存放后台返回的语句代码,目的是把参数放到attachmentNames,attachmentPath,attachmentFilenames中。

后台代码:

public String execute_attachment(
			String filename,//文件名
			Integer attachmentNum,//文件数量
			Boolean mark,//标识
			@RequestParam(value = "attachmentFile", required = false) MultipartFile file,//文件
			HttpServletRequest request, ModelMap model) {
		CmsSite site = CmsUtils.getSite(request);
		WebErrors errors = validateUpload(file, request);
		if (errors.hasErrors()) {
			model.addAttribute("error", errors.getErrors().get(0));
			return FrontUtils.getTplPath(request, site.getSolutionPath(),
					TPLDIR_MESSAGE, RESULT_PAGE_ATT);
		}
		String origName = file.getOriginalFilename();//获取文件原始名称
		String ext = FilenameUtils.getExtension(origName).toLowerCase(
				Locale.ENGLISH);
		// TODO 检查允许上传的后缀
		try {
			String fileUrl;
			if (site.getConfig().getUploadToDb()) {
				String dbFilePath = site.getConfig().getDbFileUri();
				fileUrl = dbFileMng.storeByExt(site.getUploadPath(), ext, file
						.getInputStream());
				// 加上访问地址
				fileUrl = request.getContextPath() + dbFilePath + fileUrl;
			} else if (site.getUploadFtp() != null) {
				Ftp ftp = site.getUploadFtp();
				String ftpUrl = ftp.getUrl();
				fileUrl = ftp.storeByExt(site.getUploadPath(), ext, file
						.getInputStream());
				// 加上url前缀
				fileUrl = ftpUrl + fileUrl;
			} else {
				String ctx = request.getContextPath();
				fileUrl = fileRepository.storeByExt(site.getUploadPath(), ext,
						file);//此处是上传的核心代码
				// 加上部署路径
				fileUrl = ctx + fileUrl;
			}
			model.addAttribute("attachmentPath", fileUrl);
			model.addAttribute("attachmentName", origName);
			model.addAttribute("attachmentNum", attachmentNum);
		} catch (IllegalStateException e) {
			model.addAttribute("error", e.getMessage());
			log.error("upload file error!", e);
		} catch (IOException e) {
			model.addAttribute("error", e.getMessage());
			log.error("upload file error!", e);
		}
		return FrontUtils.getTplPath(request, site.getSolutionPath(),
				TPLDIR_MESSAGE, RESULT_PAGE_ATT);
	}

public String storeByExt(String path, String ext, MultipartFile file)
			throws IOException {
		String filename = UploadUtils.generateFilename(path, ext);
		File dest = new File(ctx.getRealPath(filename));
		dest = UploadUtils.getUniqueFile(dest);
		store(file, dest);
		return filename;
	}

private void store(MultipartFile file, File dest) throws IOException {
		try {
			UploadUtils.checkDirAndCreate(dest.getParentFile());
			file.transferTo(dest);
		} catch (IOException e) {
			log.error("Transfer file error when upload file", e);
			throw e;
		}
	}

这里利用spring的MultipartFile类来上传文件,这样由之前编辑好的路径,文件就实现读取上传了。具体改上传的方法,可以参考某博主的文章:http://blog.sina.com.cn/s/blog_8fb83eec0100wm2r.html。

文件的下载:

[#if message.attachments?size gt 0]
				[#list message.attachments as a]
						  <a id="attach${a_index}">${a.name}</a>
				[/#list]
			[/#if]
$(function() {
	Cms.message_attachment("${base}","${message.id}","${message.attachments?size}","attach");
});

Cms.message_attachment = function(base, messageId, n, prefix) {
	//alert(base+","+messageId+","+n+","+prefix);
	$.get(base + "/message_attachment_url.jspx", {
		"cid" : messageId,
		"n" : n
	}, function(data) {
		var url;
		for (var i = 0;i < n; i++) {
			url = base + "/message_attachment.jspx?cid=" + messageId + "&i=" + i
					+ data[i];
			
			$("#" + prefix + i).attr("href", url);
		}
	}, "json");
}

取到的参数:根路径base,信息编号messageId,数量n,前缀prefix。提交的url:message_attachment_url.jspx,作用是将附件链接加上href,链接到url上,当点击链接时,message_attachment.jspx链接到后台地址,根据拼接的参数,下载文件,后台代码:

@RequestMapping(value = "/message_attachment_url.jspx", method = RequestMethod.GET)
	public void url(Integer cid, Integer n, HttpServletRequest request,
			HttpServletResponse response, ModelMap model) {
		if (cid == null || n == null) {
			return;
		}
		CmsConfig config = CmsUtils.getSite(request).getConfig();
		String code = config.getDownloadCode();//产生下载码,用于后续的下载工作,目的为了掩藏文件的真实路径
		long t = System.currentTimeMillis();
		JSONArray arr = new JSONArray();
		String key;
		for (int i = 0; i < n; i++) {
			key = pwdEncoder.encodePassword(cid + ";" + i + ";" + t, code);
			arr.put("&t=" + t + "&k=" + key);
		}
		ResponseUtils.renderText(response, arr.toString());
	}

@RequestMapping(value = "/message_attachment.jspx", method = RequestMethod.GET)
	public void attachment(Integer cid, Integer i, Long t, String k,
			HttpServletRequest request, HttpServletResponse response,
			ModelMap model) throws IOException {
		CmsConfig config = CmsUtils.getSite(request).getConfig();
		String code = config.getDownloadCode();//获取之前存入的下载码
		int h = config.getDownloadTime() * 60 * 60 * 1000;
		if (pwdEncoder.isPasswordValid(k, cid + ";" + i + ";" + t, code)) {//下载码两相比对
			long curr = System.currentTimeMillis();
			if (t + h > curr) {
				CmsMessage cm = messageMng.findById(cid);//得到信息
				System.out.println(cm.getTitleHtml()+"title");
				if (cm != null) {
					List<CmsMessageAttachment> list = cm.getAttachments();//获得所有附件
					if (list.size() > i) {
						CmsMessageAttachment cma = list.get(i);
						response.sendRedirect(cma.getPath());//返回路径
						return;
					} else {
						log.info("download index is out of range: {}", i);
					}
				} else {
					log.info("Message not found: {}", cid);
				}
			} else {
				log.info("download time is expired!");
			}
		} else {
			log.info("download key error!");
		}
		response.setStatus(HttpServletResponse.SC_NOT_FOUND);
	}

至此附件的下载工作基本完成。

本文章恐怕只有笔者自己能够看明白,写的不清楚之处,大家也不用喷了,本来当做笔记用的,未必期望大家都从中受益。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值