【问题标题】:Consume JSON / Base64 encoded file in Android / Java在 Android / Java 中使用 JSON / Base64 编码文件
【发布时间】: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 );
  • 在我的回答中检查我的(编辑的)评论。

标签: java android json http inputstream


【解决方案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 你的结构是静态的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-27
  • 2021-02-04
  • 2016-04-04
  • 1970-01-01
  • 2020-04-06
相关资源
最近更新 更多