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

标签: json Java Android HTTP
发布时间: 2017/3/19 19:14:50
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

我有一个网站 service 能够返回 PDF 文件在两个方面︰

原料︰ 该文件只包含在响应正文中。例如︰

HTTP/1.1 200 OK
Content-Type: application/pdf

<file_contents>

JSON︰ 该文件是编码 (基地 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);

对于第一次的情况 (原料响应),响应正文将文件本身。这意味着, getPDFFileContentsInputStream(InputStream) 方法实现是微不足道的︰

@NonNull InputStream getPDFFileContentsInputStream(@NonNull InputStream bodyStream) {
    // Return the input
    return bodyStream;
}

问题是︰如何实现 getPDFFileContentsInputStream(InputStream) 的第二个案例 (JSON 响应) 方法?

解决方法 1:

你可以使用任何 json 解析器 (像杰克逊或 Gson),然后使用 Base64InputStream 从 apache 共同性的编解码器。

编辑︰你可以获得一个输入的流从字符串使用 ByteArrayInputStream ,即

InputStream stream = new ByteArrayInputStream(exampleString.getBytes(StandardCharsets.UTF_8));

作为说明在这里

编辑 2:这将导致 2 传递的数据,如果文件比较大,你可能有内存问题。为了解决它,你可以使用杰克逊和解析内容自己像这样的例子,而不是获取整个对象通过反射。你可以包装在另一个原始输入的流说, ExtractingInputStream ,和这将直到编码部分跳过基础输入流中的数据。然后你可以把这包装 ExtractingInputStream 实例在 Base64InputStream 。一个简单的算法来跳过不必要的部分将会像这样︰ 在构造函数中的 ExtractingInputStream ,跳过直到你已经读了三个引号。在读取方法返回什么基础流除了返回-1 如果基础流返回引号,对应于基地 64 编码数据的末尾。

赞助商