如何将MultipartFile压缩为GZIP流并获取压缩后大小
解决方案
核心问题分析
你之前使用OutputStream.nullOutputStream()会直接丢弃压缩后的数据,自然无法获取压缩流和大小。必须用可缓存的输出流保存压缩结果,再转换为输入流并计算大小。
内存缓存方案(适合小文件)
直接用ByteArrayOutputStream缓存压缩数据,既能拿到压缩后的字节数组,也能直接获取大小:
param: MultipartFile file try (InputStream inputStream = file.getInputStream(); ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); GZIPOutputStream gzipOut = new GZIPOutputStream(byteArrayOut)) { // 将原始数据写入GZIP流完成压缩 IOUtils.copyLarge(inputStream, gzipOut); // 必须调用finish(),确保GZIP内部缓冲区的剩余数据写入 gzipOut.finish(); // 获取压缩后的大小和输入流 byte[] compressedBytes = byteArrayOut.toByteArray(); long compressedSize = compressedBytes.length; InputStream compressedInputStream = new ByteArrayInputStream(compressedBytes); // 注意:如果你的sendCompressed需要的是GZIPInputStream,那是用于解压的流,并非发送压缩数据所需 // 若确实需要GZIPInputStream(比如验证压缩内容),可以这样创建: // GZIPInputStream gzipIn = new GZIPInputStream(new ByteArrayInputStream(compressedBytes)); sendCompressed(compressedInputStream, compressedSize); } catch (IOException e) { e.printStackTrace(); }
临时文件方案(适合大文件)
如果文件过大,内存缓存可能导致OOM,改用临时文件存储压缩结果:
param: MultipartFile file try (InputStream inputStream = file.getInputStream(); File tempFile = File.createTempFile("gzip_temp_", ".gz"); FileOutputStream fileOut = new FileOutputStream(tempFile); GZIPOutputStream gzipOut = new GZIPOutputStream(fileOut)) { IOUtils.copyLarge(inputStream, gzipOut); gzipOut.finish(); // 获取压缩后的大小和输入流 long compressedSize = tempFile.length(); InputStream compressedInputStream = new FileInputStream(tempFile); sendCompressed(compressedInputStream, compressedSize); // 临时文件在JVM退出时自动删除 tempFile.deleteOnExit(); } catch (IOException e) { e.printStackTrace(); }
关键注意点
- 必须调用
GZIPOutputStream.finish()或关闭流,否则GZIP内部缓冲区的最后一部分数据不会写入目标输出流。 GZIPInputStream是用于读取GZIP压缩数据并解压的流,发送压缩数据时只需要原始的压缩字节流(ByteArrayInputStream/FileInputStream即可),不要混淆两者的用途。
内容的提问来源于stack exchange,提问作者Edgar Silva
相关产品推荐
相关产品推荐

