在 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 中的示例吗? JsonParserJackson 类有一个名为 getInputSource 的方法,这是一个“可用于访问用于访问正在解析的输入的对象的方法;这通常是 InputStream 或 Reader,具体取决于什么根据他们的doc,解析器是用“构造的”。如果你还有进一步的帮助,我可能需要把方法写完整。试试自己,如果你不能,我会帮忙。 如果你能写出方法实现我会很高兴,以便我接受你的回答 @GabrielHuff 你的结构是静态的吗?

以上是关于在 Android / Java 中使用 JSON / Base64 编码文件的主要内容,如果未能解决你的问题,请参考以下文章

在 Android / Java 中使用 JSON / Base64 编码文件

java - 如何使用json中提供的多个联系人数据在java中的android中添加新的电话联系人

如何在 Android Java 中发布 json 数据?

如何使用 REST 将 Json 字符串发送到 android 参数中的 java webservice?

如何在 Java Android App 中使用从 Webserver 检索到的 JSON 来动态创建和使用对象

在java Android中获取JSON嵌套对象的特定索引