ByteArrayOutputStream - 错误地生成了带有特殊字符的条目
ByteArrayOutputStream - entries generated with special characters wrongly
我正在使用 ByteArrayOutputStream 和 ZipOutputStream 生成一个 zip 文件。 ZipEntry 中的文件名是正确的,具有正确的编码。
当调用“ByteArrayOutputStream.toByteArray()”并且正确创建 zip 文件但 zipEntries 生成在“cp866”时,问题就来了。在控制器中,return 类型是 ResponseEntity.
下面是部分代码
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();
而 return 到 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”。
我尝试过的:
- returning 一个 StreamingResponseBody(而不是 byte[])
- 在 zipEntry 文件名字符串中指定字符集
- 在 zipEntry 对象中指定字符集
- convert do base64(生成的文件损坏)
所有可能性都没有成功
解决方案:使用正确的 ZipOutputStream
构造函数,即采用 OutputStream 和 编码的构造函数。
旁注:你打错了。这个:
headers.setContentType(MediaType.parseMediaType("application/zip; charset-utf-8"));
不正确。是 charset=utf-8
。注意等号。然而,这也不正确。 ZIP 文件没有 字符集编码。是二进制数据。 JPG 文件也没有,同理。正确的 MIME 类型只是 application/zip
,仅此而已。
完整解释
您不能使用 mime headers 传送 zip 文件 中 条目的字符集编码。它编码在 zip 文件本身中。
因此,在 zip 文件本身中对其进行编码。很容易做到!
new ZipOutputStream(byteArrayOutputStream, StandardCharsets.UTF_8);
这是您唯一需要进行的更新。
我正在使用 ByteArrayOutputStream 和 ZipOutputStream 生成一个 zip 文件。 ZipEntry 中的文件名是正确的,具有正确的编码。
当调用“ByteArrayOutputStream.toByteArray()”并且正确创建 zip 文件但 zipEntries 生成在“cp866”时,问题就来了。在控制器中,return 类型是 ResponseEntity
下面是部分代码
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();
而 return 到 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”。
我尝试过的:
- returning 一个 StreamingResponseBody(而不是 byte[])
- 在 zipEntry 文件名字符串中指定字符集
- 在 zipEntry 对象中指定字符集
- convert do base64(生成的文件损坏)
所有可能性都没有成功
解决方案:使用正确的 ZipOutputStream
构造函数,即采用 OutputStream 和 编码的构造函数。
旁注:你打错了。这个:
headers.setContentType(MediaType.parseMediaType("application/zip; charset-utf-8"));
不正确。是 charset=utf-8
。注意等号。然而,这也不正确。 ZIP 文件没有 字符集编码。是二进制数据。 JPG 文件也没有,同理。正确的 MIME 类型只是 application/zip
,仅此而已。
完整解释
您不能使用 mime headers 传送 zip 文件 中 条目的字符集编码。它编码在 zip 文件本身中。
因此,在 zip 文件本身中对其进行编码。很容易做到!
new ZipOutputStream(byteArrayOutputStream, StandardCharsets.UTF_8);
这是您唯一需要进行的更新。