有趣的是,我在这里做了一些测试,无论流的来源如何,当你使用
InputStreamReader
读取
Base64InputStream
时,它确实会抛出异常,但是当你将其作为二进制流读取时,它却可以完美地工作。正如Trashgod所提到的,Base64编码是帧结构的。
InputStreamReader
实际上应该在
Base64InputStream
上再次调用
flush()
,以查看是否还有更多数据返回。
我没有看到其他修复此问题的方法,除了实现自己的Base64InputStreamReader
或Base64Reader
。这实际上是一个bug,请参见Keith的答案。
作为解决方法,您还可以将其存储在DB中的BLOB而不是CLOB中,并使用PreparedStatement#setBinaryStream()
。无论它被存储为二进制数据还是其他内容都没有关系。您不希望具有如此大的Base64数据可索引或可搜索。
更新:由于这不是一个选择,让Apache Commons Codec的人修复我报告的
Base64InputStream
错误
CODEC-101可能需要一些时间,您可以考虑使用另一个第三方Base64 API。我在这里找到了一个
here(公共领域,所以您可以随意使用它,甚至放在自己的包中),我在这里测试过,它运行良好。
InputStream base64 = new Base64.InputStream(input, Base64.ENCODE);
更新2:commons codec的开发者很快修复了这个问题。
Index: src/java/org/apache/commons/codec/binary/Base64InputStream.java
===================================================================
--- src/java/org/apache/commons/codec/binary/Base64InputStream.java (revision 950817)
+++ src/java/org/apache/commons/codec/binary/Base64InputStream.java (working copy)
@@ -145,21 +145,41 @@
} else if (len == 0) {
return 0;
} else {
- if (!base64.hasData()) {
- byte[] buf = new byte[doEncode ? 4096 : 8192];
- int c = in.read(buf);
-
-
- if (c > 0 && b.length == len) {
- base64.setInitialBuffer(b, offset, len);
+ int readLen = 0;
+
+ while (readLen == 0) {
+ if (!base64.hasData()) {
+ byte[] buf = new byte[doEncode ? 4096 : 8192];
+ int c = in.read(buf);
+
+
+ if (c > 0 && b.length == len) {
+ base64.setInitialBuffer(b, offset, len);
+ }
+ if (doEncode) {
+ base64.encode(buf, 0, c);
+ } else {
+ base64.decode(buf, 0, c);
+ }
}
- if (doEncode) {
- base64.encode(buf, 0, c);
- } else {
- base64.decode(buf, 0, c);
- }
+ readLen = base64.readResults(b, offset, len);
}
- return base64.readResults(b, offset, len);
+ return readLen;
}
}
我在这里尝试过,它运行良好。