1. 简介
提供基于spring实现文件(笔记附件)的上传和下载的完整方案。方案将文件上传,并将文件名称作为字段与关联的笔记绑定在一起,更新笔记在数据库中的记录。显示笔记时,根据笔记所绑定的文件名生成下载路径,提交给服务端完成下载。
2. 文件上传
2. 1 前端
在html中插入一个表单用于提交文件
<form id= "uploadForm">
<input type="file" name="file" id="file"/>
<input type="button" id="upload" value="上传附件"/>
</form>
编写js给button单击事件,发送ajax请求,将文件数据上传给服务端,服务端返回存储的真实文件名,将文件名绑定在笔记元素上,在保存笔记时,将文件名写入相应笔记的数据库记录中。
//给上传文件按钮绑定事件
$("#upload").click(uploadFile);
function uploadFile(){
//获得上传文件
$.ajax({
url: 'file/upload.do',
type: 'POST',
cache: false,
data: new FormData($('#uploadForm')[0]),
processData: false,
contentType: false,
success:function(result){
var $checkedLi = $("#note_list li a.checked").parent();
$checkedLi.data("attachment",result.data);
alert("上传成功"+result.data);
}
});
}
1. 2 后端
采用CommonsMultipartResolver,需要导入commons-fileupload-1.2.1.jar和commons-io-1.3.2.jar,sc是ServletContext的引用,用实现ServletContextAware接口的方式获得。
public JsonResult upload(HttpServletRequest request,HttpServletResponse response) throws Exception{
JsonResult result = new JsonResult();
try{
request.setCharacterEncoding("utf-8");
//创建一个通用的多部分解析器
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(sc);
//判断 request 是否有文件上传,即多部分请求
if(multipartResolver.isMultipart(request)){
//转换成多部分request
MultipartHttpServletRequest multiRequest =
multipartResolver.resolveMultipart(request);
//取得request中的所有文件名
Iterator<String> iter = multiRequest.getFileNames();
while(iter.hasNext()){
//取得上传文件
MultipartFile file = multiRequest.getFile(iter.next());
if(file != null){
//取得当前上传文件的文件名称
String myFileName = file.getOriginalFilename();
//如果名称不为“”,说明该文件存在,否则说明该文件不存在
if(myFileName.trim() !=""){
//重命名上传后的文件名
String fileName = file.getOriginalFilename();
//定义上传路径
String dirPath = sc.getRealPath("/WEB-INF/files/");
File dir = new File(dirPath);
if(!dir.exists()){
dir.mkdirs();
}
File localFile = new File(dir, NoteUtil.creatId().substring(30)+"-"+fileName);
file.transferTo(localFile);
//结果绑定文件路径
result.setStatus(0);
result.setData(localFile.getName());
result.setMsg("上传成功");
}
}
}
}
}catch(Exception e){
e.printStackTrace();
throw e;
}
result.setStatus(1);
return result;
}
2. 文件下载
2. 1 前端
由于get请求存在中文编码异常的问题,所以采用post请求,首先获取元素中绑定的文件名,生成一个表单
if(attachment!=null){
var form_str = '<form action="file/download.do" method="post">'+
'<input type="hidden" name="fileName" value="'+attachment+'"></input>'+
'<input type="submit" value="下载附件"></input>'+
'</form>';
$("#download_attachment").html(form_str);
}
2. 2 后端
后端需要解决中文文件名无法正常显示的问题,采用ISO8859-1字符集
public void download(HttpServletResponse response, String fileName) throws Exception{
System.out.println(fileName);
String filePath = "/WEB-INF/files/"+fileName;
String fileFullPath = sc.getRealPath(filePath);
File file = new File(fileFullPath);
if(file.exists()){
//重置response
response.reset();
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//设置http头信息的内容
// response.addHeader("Content-Disposition", "attachment;filename=\""+fileName+"\"");
//解决中文文件名显示问题
response.addHeader("Content-Disposition", "attachment;filename="+new String(fileName.getBytes("gb2312"),"ISO8859-1"));
//设置文件长度
int fileLength = (int)file.length();
response.setContentLength(fileLength);
if(fileLength!=0){
InputStream inStream = new FileInputStream(file);
byte[] buf = new byte[4096];
//创建输出流
ServletOutputStream servletOS = response.getOutputStream();
int readLength;
//读取文件内容并写入到response的输出流当中
while((readLength = inStream.read(buf))!=-1){
servletOS.write(buf, 0, readLength);
}
//关闭输入流
inStream.close();
//刷新输出流缓冲
servletOS.flush();
//关闭输出流
servletOS.close();
}
}else{
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("文件\""+fileName + "\"不存在");
}
}