From afec4e64e04f20134151a54f113862e34964f3f0 Mon Sep 17 00:00:00 2001 From: Vasiliy Mikhailov Date: Thu, 25 Jun 2026 07:32:41 +0300 Subject: [PATCH] Read the full stream in FileUtils.imageToBase64ByStream The method sized its buffer from in.available() (only an estimate, not the total) and called in.read(data) once while ignoring the returned count, so any stream that does not return all bytes in a single read (buffered/network streams) left the buffer partially filled with trailing zeros, producing truncated/corrupted base64. Read the stream fully via IOUtils.toByteArray (commons-io, already imported). Fills the existing empty testImageToBase64ByStream with a regression test. --- .../weixin/common/util/fs/FileUtils.java | 5 +--- .../weixin/common/util/fs/FileUtilsTest.java | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java index 4a267153c6..8419c87d5a 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/fs/FileUtils.java @@ -57,13 +57,10 @@ public static File createTmpFile(InputStream inputStream, String name, String ex * @return base64编码 */ public static String imageToBase64ByStream(InputStream in) { - byte[] data = null; // 读取图片字节数组 try { - data = new byte[in.available()]; - in.read(data); // 返回Base64编码过的字节数组字符串 - return Base64.getEncoder().encodeToString(data); + return Base64.getEncoder().encodeToString(IOUtils.toByteArray(in)); } catch (IOException e) { e.printStackTrace(); } finally { diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/fs/FileUtilsTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/fs/FileUtilsTest.java index 5a25fb1493..3ab603e47c 100644 --- a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/fs/FileUtilsTest.java +++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/fs/FileUtilsTest.java @@ -6,8 +6,10 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.nio.charset.Charset; import java.nio.file.Files; +import java.util.Base64; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -30,5 +32,31 @@ public void testTestCreateTmpFile() { @Test public void testImageToBase64ByStream() { + byte[] original = new byte[5000]; + for (int i = 0; i < original.length; i++) { + original[i] = (byte) (i % 256); + } + // A stream that returns at most 16 bytes per read() call (like a network stream), + // so a single in.read(buffer) does not fill the buffer. + InputStream chunked = new InputStream() { + private final ByteArrayInputStream delegate = new ByteArrayInputStream(original); + + @Override + public int read() { + return delegate.read(); + } + + @Override + public int read(byte[] b, int off, int len) { + return delegate.read(b, off, Math.min(len, 16)); + } + + @Override + public int available() { + return delegate.available(); + } + }; + String result = FileUtils.imageToBase64ByStream(chunked); + assertThat(result).isEqualTo(Base64.getEncoder().encodeToString(original)); } }