如何使用JAX-RS从Java服务器端返回Zip文件?

时间:2014-04-05 13:24:16

标签: java jersey jax-rs filestream outputstream

我想使用JAX-RS从服务器端java返回一个压缩文件到客户端。

我尝试了以下代码,

@GET
public Response get() throws Exception {

    final String filePath = "C:/MyFolder/My_File.zip";

    final File file = new File(filePath);
    final ZipOutputStream zop = new ZipOutputStream(new FileOutputStream(file);

    ResponseBuilder response = Response.ok(zop);
    response.header("Content-Type", "application/zip");
    response.header("Content-Disposition", "inline; filename=" + file.getName());
    return response.build();
}

但我得到的例外如下,

SEVERE: A message body writer for Java class java.util.zip.ZipOutputStream, and Java type class java.util.zip.ZipOutputStream, and MIME media type application/zip was not found
SEVERE: The registered message body writers compatible with the MIME media type are:
*/* ->
  com.sun.jersey.core.impl.provider.entity.FormProvider

有什么问题,我该如何解决这个问题?

4 个答案:

答案 0 :(得分:9)

您在泽西岛委托了解如何序列化ZipOutputStream的知识。因此,使用您的代码,您需要为ZipOutputStream实现自定义MessageBodyWriter。相反,最合理的选择可能是将字节数组作为实体返回。

您的代码如下:

@GET
public Response get() throws Exception {
    final File file = new File(filePath);

    return Response
            .ok(FileUtils.readFileToByteArray(file))
            .type("application/zip")
            .header("Content-Disposition", "attachment; filename=\"filename.zip\"")
            .build();
}

在此示例中,我使用 Apache Commons IO 中的FileUtils将File转换为byte [],但您可以使用其他实现。

答案 1 :(得分:3)

在Jersey 2.16文件下载非常简单

以下是ZIP文件的示例

@GET
@Path("zipFile")
@Produces("application/zip")
public Response getFile() {
    File f = new File(ZIP_FILE_PATH);

    if (!f.exists()) {
        throw new WebApplicationException(404);
    }

    return Response.ok(f)
            .header("Content-Disposition",
                    "attachment; filename=server.zip").build();
}

答案 2 :(得分:3)

您可以将附件数据写入StreamingOutput类,Jersey将从中读取。

@Path("/report")
@GET
@Produces(MediaType.TEXT_PLAIN)
public Response generateReport() {
    String data = "file contents"; // data can be obtained from an input stream too.
    StreamingOutput streamingOutput = outputStream -> {
        ZipOutputStream zipOut = new ZipOutputStream(new BufferedOutputStream(outputStream));
        ZipEntry zipEntry = new ZipEntry(reportData.getFileName());
        zipOut.putNextEntry(zipEntry);
        zipOut.write(data); // you can set the data from another input stream
        zipOut.closeEntry();
        zipOut.close();
        outputStream.flush();
        outputStream.close();
    };

    return Response.ok(streamingOutput)
            .type(MediaType.TEXT_PLAIN)
            .header("Content-Disposition","attachment; filename=\"file.zip\"")
            .build();
}

答案 3 :(得分:1)

我不确定在泽西岛是否有可能只是通过带注释的方法返回一个流。我想应该打开相当流,并将文件内容写入流。看看this博文。我想你应该实现类似的东西。