我有一个webapp,允许用户选择图像,然后下载它们。对于单个图像,我使用HTML5的锚点下载,它的工作非常精彩。现在我需要允许他们选择多个图像,并将它们下载为.zip文件。我正在使用api将每个图像作为InputStream并返回Jersey响应。
我是拉链的新手,我对使用InputStream进行压缩的方式有点困惑。
对于单张图片,它的工作原理如下:
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();
}
它并不多,但这是我迄今为止的多个图像
的javapublic 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
}
...
}
我只是不知道如何处理多个InputStream,而且似乎我不应该有多个,对吧?
答案 0 :(得分:2)
每张图片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);