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

Consume JSON / Base64 encoded file in Android / Java

我有一个网络服务能够以两种方式返回 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)方法?

您可以使用任何 json 解析器(如 Jackson 或 Gson),然后使用 apache-commons 编解码器中的 Base64InputStream

编辑: 您可以使用 ByteArrayInputStream 从字符串中获取输入流,即

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

如所述here

EDIT 2: 这将导致 2 传递数据,如果文件很大,您可能会遇到内存问题。要解决它,你可以使用 Jackson 并像 this 示例那样自己解析内容,而不是通过反射获取整个对象。 你可以将原始输入流包装在另一个输入流中,比如ExtractingInputStream,这将跳过底层输入流中的数据,直到编码部分。然后您可以将此 ExtractingInputStream 实例包装在 Base64InputStream 中。跳过不必要部分的简单算法如下:在 ExtractingInputStream 的构造函数中,跳过直到读完三个引号。在read方法中,return是什么底层流returns except return -1 如果底层流是returns引号,对应base 64编码数据的结尾。