【问题标题】:Zip multiple objects from inputStream in Java从 Java 中的 inputStream 压缩多个对象
【发布时间】:2014-04-11 04:39:38
【问题描述】:

我有一个网络应用程序,允许用户选择图像然后下载它们。对于单个图像,我使用 HTML5 的锚点下载,效果很好。现在我需要允许他们选择多个图像,并将它们下载为 .zip 文件。我正在使用 api 将每个图像作为 InputStream 并返回 Jersey 响应。

我是 zip 的新手,我对 InputStream 的 zip 应该如何工作感到有些困惑。

对于单张图片,它的工作原理如下:

try {
    InputStream imageInputStream = ImageStore.getImage(imageId);

    if (imageInputStream == null) {
        XLog.warnf("Unable to find image [%s].", imageId);
        return Response.status(HttpURLConnection.HTTP_GONE).build();
    }

    Response.ResponseBuilder response = Response.ok(imageInputStream);
    response.header("Content-Type", imageType.mimeType());
    response.header("Content-Disposition", "filename=image.jpg");

    return response.build();
}

这并不多,但这是我目前拥有的用于多张图片

的java
public Response zipAndDownload(List<UUID> imageIds) {
    try {
        // TODO: instantiate zip file?

        for (UUID imageId : imageIds) {
            InputStream imageInputStream = ImageStore.getImage(imageId);
            // TODO: add image to zip file (ZipEntry?)
        }

        // TODO: return zip file
    }
    ...
}

我就是不知道如何处理多个InputStreams,而且我似乎不应该有多个,对吧?

【问题讨论】:

    标签: java zip inputstream


    【解决方案1】:

    InputStream 每张图片都可以。要压缩文件,您需要为它们创建一个 .zip 文件并获取 ZipOutputStream 来写入它:

    File zipFile = new File("/path/to/your/zipFile.zip");
    ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
    

    为每个图像创建一个新的ZipEntry,将其添加到ZipOutputSteam,然后将图像的InputStream 中的字节复制到ZipOutputStream

    ZipEntry ze = new ZipEntry("PrettyPicture1.jpg");
    zos.putNextEntry(ze);
    byte[] bytes = new byte[1024];
    int count = imageInputStream.read(bytes);
    while (count > -1)
    {
        zos.write(bytes, 0, count);
        count = imageInputStream.read(bytes);
    }
    imageInputStream.close();
    zos.closeEntry();
    

    添加所有条目后,关闭ZipOutputStream

    zos.close();
    

    现在您的 zipFile 指向一个包含图片的 zip 文件,您可以随心所欲地做任何事情。您可以像使用单个图像一样返回它:

    BufferedInputStream zipFileInputStream = new BufferedInputStream(new FileInputStream(zipFile));
    Response.ResponseBuilder response = Response.ok(zipFileInputStream);
    

    但内容类型和性格不同:

    response.header("Content-Type", MediaType.APPLICATION_OCTET_STREAM_TYPE);
    response.header("Content-Disposition", "attachment; filename=zipFile.zip");
    

    注意:您可以使用Guava's ByteStreams helper 中的copy 方法来复制流,而不是手动复制字节。只需将 while 循环和它之前的 2 行替换为以下行:

    ByteStreams.copy(imageInputStream, zos);
    

    【讨论】:

    • 这很好用。谢谢你。出于某种原因,我的印象是多个 InputStreams 是不好的做法,但在这种情况下,它非常简单。现在让它正确下载到客户端。
    • 他应该不需要创建文件,只需将ZipOutputStream 连接到响应输出流即可。
    • @EJP,我在尝试你的建议时遇到了类似的问题,它给出了这个错误MessageBodyWriter not found for media type=application/octet-stream, type=class java.util.zip.ZipOutputStream, genericType=class java.util.zip.ZipOutputStream.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-28
    相关资源
    最近更新 更多