Jersey 框架开发Restful-Jersey 上传下载文件。

上传

 

maven中添加multipart的依赖:

 
  org.glassfish.jersey.media 
  jersey-media-multipart 
   2.25
 



接着,需要在Jersey中引入MultipartFeature。MultiPartFeature是Jersey中针对Multipart的一种特征。

在Jersey中有几种注册MultipartFeature的方式:

1,在web.xml中注册:只需要在Jersey的ServletContainer中添加initparam即可:


        jersey.config.server.provider.classnames
        org.glassfish.jersey.media.multipart.MultiPartFeature
    

 

配置完成之后,只需要完成对应的资源类即可:

@POST
@Path("image1")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String upload(@FormDataParam("file") InputStream fileInputStream,
        @FormDataParam("file") FormDataContentDisposition disposition, @Context ServletContext ctx) {
    
    return "success";
}

简单解释一下这段代码:
1,请求必须是POST的,这个不用多说;
2,请求返回json格式响应;
3,Consumes这次设置的是MediaType.MULTIPART_FORM_DATA,这个很重要,因为要能够上传,需要要求表单的提交格式为multipart/form-data;
4,重点在于资源方法的参数,在这里,我们使用了@FormDataParam(该标签来源于jersey的multipart包),该标签能够在资源方法上绑定请求编码类型为multipart/form-data中的每一个实体项。该标签可以绑定如下一些类型:

该标签可以绑定如下一些类型:

  • FormDataBodyPart;
  • List
  • FormDataContentDisposition;
  • List
  • InputStream;

看一个完整的上传文件的例子,使用两种方式完成:

(建议使用第一种)

第一种方式我们采用的是直接使用InputStream来提供上传文件的输入流;

@POST
@Path("image1")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String upload(@FormDataParam("file") InputStream fileInputStream,
        @FormDataParam("file") FormDataContentDisposition disposition, @Context ServletContext ctx) {

    File upload = new File(ctx.getRealPath("/upload"),
            UUID.randomUUID().toString() + "." + FilenameUtils.getExtension(disposition.getFileName()));
    try {
        FileUtils.copyInputStreamToFile(fileInputStream, upload);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return "success";
}

第二种方式,我们使用较为底层的FormDataBodyPart来完成。综合两种方式,更建议使用第一种方式来完成文件上传。

@POST
@Path("image2")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String upload2(@FormDataParam("file") FormDataBodyPart bp, @Context ServletContext ctx) {
    File upload = new File(ctx.getRealPath("/upload"), UUID.randomUUID().toString() + "."
            + FilenameUtils.getExtension(bp.getFormDataContentDisposition().getFileName()));
    try {
        FileUtils.copyInputStreamToFile(bp.getValueAs(InputStream.class), upload);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return "success";
}

 

----------------------------------------------------------------------------------

下载

下载重点在于下载的相应(repsonse)的构造。所以在Jersey的下载演示中,我们重点在于介绍Jersey怎么使用Response对象来构造特殊的响应。

基本的Jersey中用于下载的代码:

 

@GET
@Path("/images/{name}")
public void showImg(@PathParam("name") String imageName, @Context HttpServletResponse response,
        @Context ServletContext ctx) throws IOException {
    response.setHeader("Content-disposition", "attachment;filename="+imageName);
    response.setHeader("Cache-Control", "no-cache");
    File f = new File(ctx.getRealPath("/upload"), imageName);
    FileUtils.copyFile(f, response.getOutputStream());
}


可以看到,这段代码其实和以前使用Servlet来完成下载没有任何区别,原因就在于我们利用了Jersey的@Context标签可以注入HttpServletResponse对象的特性来完成的下载(注意,演示代码没有考虑到文件是否存在之类的情况);

在JAX-RS中,为我们提供了一个更为灵活的Response对象,通过建造模式(build pattern),能够非常方便的构造出适合的响应。我们先来看第一种使用Response完成下载的代码:

@GET
@Path("/images2/{name}")
public Response showImg(@PathParam("name") String imageName, @Context ServletContext ctx) throws IOException {
    File f = new File(ctx.getRealPath("/upload"), 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的输出流,即可。

 

小结

 

本节简单的阐述了在Jersey中对文件的上传下载的基本操作,需要重点注意的是,要在Jersey中对上传进行操作,必须要引入MultipartFeature,才能针对multipart/form-data等特殊请求编码格式进行处理。

转载

本文来自https://www.jianshu.com/p/16aa75e79baf

你可能感兴趣的:(Jersey 框架开发Restful-Jersey 上传下载文件。)