记录一下jersey框架中的文件下载方法
@GET
@Path("/images")
public Response showImg(@Context HttpServletResponse response, @Context ServletContext ctx) throws IOException {
//获取文件路径
String imageRootPath = PropertyUtil.getSpecificProperties("config/fixedRes.properties", "test.image.rootpath");
String imageName = PropertyUtil.getSpecificProperties("config/fixedRes.properties", "test.image.name");
File f = new File(imageRootPath, imageName);
if (!f.exists()) {
return Response.status(Status.NOT_FOUND).build();
} else {
return Response.ok(f).header("Content-disposition", "attachment;filename=" + imageName)
.header("Cache-Control", "no-cache").build();
}
}
这段代码关注几个点:
1,资源方法返回了一个javax.ws.rs.core.Response类,这个类可以直接被JAX-RS作为一个Response输出;
2,在代码中,如果文件找不到,我们直接使用Response类提供的status方法,构造了一个NOT_FOUND(404)状态码,并通过build方法创建一个Response对象返回,相当于就是构建了一个404状态码的响应。
3,如果文件存在,我们调用了Response的ok方法,传入了文件对象,那么JAX-RS会自动的设置本次响应状态码为200,并把文件写到响应输出流中,其次,我们采用链式调用的方式,设置了响应头,最后还是通过build方法,输出响应。总的来看,Response的这种操作方式,在开发上面还是非常方便和直观的。
对于某些没有源文件,直接输出流的内容,比如在内存中构造一个图片提供下载,或者构造一个Excel下载或者构造一个PDF文件提供下载等,就不能直接把一个原始File对象作为ok方法的参数,这个时候就需要使用到JAX-RS提供的StreamingOutput接口:
@GET
@Path("/images3/{name}")
public Response showImg2(@PathParam("name") String imageName, @Context ServletContext ctx) throws IOException {
final File f = new File(ctx.getRealPath("/upload"), imageName);
if (!f.exists()) {
return Response.status(Status.NOT_FOUND).build();
} else {
return Response.ok(new StreamingOutput() {
@Override
public void write(OutputStream output) throws IOException, WebApplicationException {
output.write(FileUtils.readFileToByteArray(f));
}
}).header("Content-disposition", "attachment;filename=" + imageName)
.header("Cache-Control", "no-cache").build();
}
}
在这端代码中,重点在于Response对象的ok方法,我们传入了一个匿名内部类,实现了StreamingOutput接口,在方法write中,直接把byte内容输出到了output参数中,这个output即为response的输出流,即可。