首先说明一下背景,在SSM框架上,需要做一个文档下载工具;
最简单的方式肯定是服务器通过请求获取文件路径,然后读取,然后回传到浏览器;
这个中间遇到了几个问题,给自己做个笔记方便以后查看;
附上代码如下:
@RestController
@RequestMapping("/downloadFile")
public class DownLoadController {
@RequestMapping("/download")
public ResponseEntity<byte[]> download(HttpServletRequest request, @RequestParam("filename") String filename,Model model) throws IOException {
// 下载文件路径
// String path = request.getServletContext().getRealPath("resource/downloadFile/");
// String path = request.getSession().getServletContext().getRealPath("resource/downloadFile/");
//上面两种方式获取路径在不同环境下可能出现null
String path = this.getClass().getClassLoader().getResource("../../resource/downloadFile/").getPath();
File file = new File(path + File.separator + filename);
HttpHeaders headers = new HttpHeaders();
// 下载显示的文件名,解决中文名称乱码问题
String downloadFielName = new String(filename.getBytes("UTF-8"), "iso-8859-1");
// 通知浏览器以attachment(下载方式)打开图片
headers.setContentDispositionFormData("attachment", downloadFielName);
// application/octet-stream : 二进制流数据(最常见的文件下载)。
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
}
}
问题1,文件路径获取的时候,在A电脑的本地服务启动环境下可以成功,但是在B电脑的本地服务上去获取的结果为Null
获取方法为 String path = request.getServletContext().getRealPath("resource/downloadFile/");
后来分析原因:在servlet中使用getServletContext.getRealPath()这个方法受到war 和non-war的影响,以及不同app server实现的影响,所以常常会得到null;
解决方法:直接获取当前类的编译绝对路径,然后再通过当前类的相对路径去找到你需要的文件位置;
举个例子,我的文件是放在webapp/resource/downloadFile/这个文件夹里面,那它相对于我当前编译类的位置就是../../resource/downloadFile/,所以我修改获取方法为
String path = this.getClass().getClassLoader().getResource("../../resource/downloadFile/").getPath();
问题2,使用Ajax发送get请求下载该文件,返回一堆字节码
这个问题处理方式是直接采用超链接,先用js给超链接赋值,指向你要的服务器文件位置,然后直接点击浏览器就会自动将返回的字节码变为文件了...
JS代码如下:
$('.download').attr('href',conf.ctx+'/downloadFile/download?filename=供应链金融业务申请资料清单.doc');
HTML如下:
<a href="" class="download">下载模板</a>