在 Android / Java 中使用 JSON / Base64 编码文件
Posted
技术标签:
【中文标题】在 Android / Java 中使用 JSON / Base64 编码文件【英文标题】:Consume JSON / Base64 encoded file in Android / Java 【发布时间】:2017-07-10 04:40:58 【问题描述】:我有一个能够以两种方式返回 PDF 文件的网络服务:
RAW:文件仅包含在响应正文中。例如:
HTTP/1.1 200 OK
Content-Type: application/pdf
<file_contents>
JSON:文件被编码(Base 64)并作为具有以下结构的 JSON:
HTTP/1.1 200 OK
Content-Type: application/json
"base64": <file_contents_base64>
我希望能够通过使用以下架构在 android
/ Java
上使用这两个服务:
// Get response body input stream (OUT OF THE SCOPE OF THIS QUESTION)
InputStream bodyStream = getResponseBodyInputStream();
// Get PDF file contents input stream from body stream
InputStream fileStream = getPDFFileContentsInputStream(bodyStream);
// Write stream to a local file (OUT OF THE SCOPE OF THIS QUESTION)
saveToFile(fileStream);
对于第一种情况(RAW 响应),响应正文将是文件本身。这意味着getPDFFileContentsInputStream(InputStream)
方法的实现是微不足道的:
@NonNull InputStream getPDFFileContentsInputStream(@NonNull InputStream bodyStream)
// Return the input
return bodyStream;
问题是:第二种情况(JSON响应)如何实现getPDFFileContentsInputStream(InputStream)
方法?
【问题讨论】:
byte[] encodedBytes = json.getBytes("base64"); byte[] decodedBytes = (new BASE64Decoder()).decodeBuffer(encodedBytes); return new ByteArrayInputStream(decodedBytes );
在我的回答中检查我的(编辑的)评论。
【参考方案1】:
您可以使用任何 json 解析器(如 Jackson 或 Gson),然后使用来自 apache-commons 编解码器的 Base64InputStream
。
编辑:您可以使用ByteArrayInputStream
从字符串中获取输入流,即
InputStream stream = new ByteArrayInputStream(exampleString.getBytes(StandardCharsets.UTF_8));
如here所述。
编辑 2: 这会导致 2 传递数据,如果文件很大,可能会出现内存问题。为了解决这个问题,您可以使用 Jackson 并像 this 示例一样自己解析内容,而不是通过反射获取整个对象。您可以将原始输入流包装在另一个中,例如 ExtractingInputStream
,并且这将跳过底层输入流中的数据,直到编码部分。然后您可以将这个ExtractingInputStream
实例包装在Base64InputStream
中。跳过不必要部分的简单算法是这样的:在ExtractingInputStream
的构造函数中,跳过三个引号。在read方法中,返回底层流返回的内容,如果底层流返回引号,则返回-1,它对应于base 64编码数据的结尾。
【讨论】:
酷!但是我怎样才能得到一个InputStream
从 JSON 中发出“base64”键的值,以便我可以将它包装在一个 Base64InputStream
中?
感谢您编辑答案。问题是:我不想通过将 base64 值作为对象(字符串)来解析 JSON 流。 PDF 文件可能很大(+10MB 没有 base64 编码),这可能会消耗比设备所能提供的更多的内存。据我所知,JsonReader
(Gson) 或 JsonParser
(Jackson) 都没有办法将值作为 InputStream
而不是 String
您检查过编辑 2 中的示例吗? JsonParser
的 Jackson
类有一个名为 getInputSource
的方法,这是一个“可用于访问用于访问正在解析的输入的对象的方法;这通常是 InputStream 或 Reader,具体取决于什么根据他们的doc,解析器是用“构造的”。如果你还有进一步的帮助,我可能需要把方法写完整。试试自己,如果你不能,我会帮忙。
如果你能写出方法实现我会很高兴,以便我接受你的回答
@GabrielHuff 你的结构是静态的吗?以上是关于在 Android / Java 中使用 JSON / Base64 编码文件的主要内容,如果未能解决你的问题,请参考以下文章
在 Android / Java 中使用 JSON / Base64 编码文件
java - 如何使用json中提供的多个联系人数据在java中的android中添加新的电话联系人
如何使用 REST 将 Json 字符串发送到 android 参数中的 java webservice?