0

我正在使用 ByteArrayOutputStream 和 ZipOutputStream 生成一个 zip 文件。ZipEntry 中的文件名正常,编码正确。当它被称为“ByteArrayOutputStream.toByteArray()”并且正确创建了 zip 文件但在“cp866”处生成了 zipEntries 时,问题就出现了。在控制器处,返回类型是 ResponseEntity<byte[]>。

下面是代码的一部分。

    byteArrayOutputStream = new ByteArrayOutputStream();
    zipOutputStream = new ZipOutputStream(byteArrayOutputStream);
    zipOutputStream.putNextEntry(new ZipEntry("ação.pdf")); //Here it is all OK
    zipOutputStream.write(inputStream.readAllBytes());
    zipOutputStream.closeEntry();

返回 RestController 的代码类似于:

    HttpHeaders headers = new HttpHeaders();
    contentDisposition =
        ContentDisposition.builder("attachment").filename("download.zip").build();

    headers.setContentDisposition(contentDisposition);
    headers.setContentLength(byteArrayOutputStream.size());
    headers.setContentType(MediaType.parseMediaType("application/zip; charset-utf-8"));
    return ResponseEntity.ok().headers(headers).body(byteArrayOutputStream.toByteArray());

在这种情况下,名为“ação.pdf”的文件会生成为“a├з├гo.pdf”,如果我在 ZipEntry 中指定字符集 ISO8859-1,它会生成为“aчуo.pdf”。

我试过的:

  • 返回一个 StreamingResponseBody(而不是 byte[])
  • 在 zipEntry 文件名字符串中指定字符集
  • 在 zipEntry 对象中指定字符集
  • 转换做base64(文件生成损坏)

没有所有可能的成功

4

1 回答 1

3

解决方案:使用正确的ZipOutputStream构造函数,即同时接受 OutputStream编码的构造函数。

旁注:你有一个错字。这:

headers.setContentType(MediaType.parseMediaType("application/zip; charset-utf-8"));

是不正确的。是charset=utf-8。注意等号。然而,这也不正确。ZIP 文件没有字符集编码。是二进制数据。JPG文件也没有,同样的原因。正确的 mime 类型仅此application/zip而已。

完整解释

无法使用 mime 标头传达zip 文件中条目的字符集编码。它被编码在 zip 文件本身中。

因此,将其编码到 zip 文件本身中。这很容易做到!

new ZipOutputStream(byteArrayOutputStream, StandardCharsets.UTF_8);

这是您需要进行的唯一更新。

于 2022-01-05T12:15:41.360 回答