Android中如何从API接口获取Excel文件并处理乱码响应?
问题解答
1. 返回数据类型说明
你在Postman中看到的PK开头的乱码响应,本质是二进制格式的XLSX类型Excel文件。XLSX格式是基于ZIP压缩规范封装的办公文档,所有ZIP格式文件的头部魔数固定为PK,Postman默认以文本形式解析二进制流就会显示后续的乱码字符。
2. Android端处理方案
整体处理逻辑分为三步:请求接口时指定接收二进制流、将流写入本地存储为.xlsx文件、调用解析库读取内容展示。
2.1 前置依赖
引入常用的轻量Excel解析库,避免Apache POI带来的过大包体积问题,在模块级build.gradle中添加依赖:
implementation 'com.github.tehras:excel-kt:1.0.2'
如果需要兼容旧版.xls格式,可以替换为POI相关依赖。
2.2 Kotlin实现示例
- 接口请求逻辑(以OkHttp为例)
val request = Request.Builder() .url("你的业务接口地址") .addHeader("Accept", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") .build() OkHttpClient().newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { // 自定义请求失败处理逻辑 } override fun onResponse(call: Call, response: Response) { if (!response.isSuccessful) return val inputStream = response.body?.byteStream() ?: return // 将二进制流写入本地缓存文件 val excelFile = File(cacheDir, "temp_excel.xlsx") excelFile.outputStream().use { output -> inputStream.copyTo(output) } // 解析文件内容 parseExcelContent(excelFile) } })
- Excel内容解析逻辑
fun parseExcelContent(file: File) { ExcelWorkbook(file) { // 读取第一个Sheet getSheet(0)?.rows?.forEachIndexed { rowIndex, row -> row.cells.forEachIndexed { cellIndex, cell -> val cellValue = cell.value // 按业务需求将内容填充到列表、表格等UI控件中 Log.d("Excel数据", "第${rowIndex+1}行第${cellIndex+1}列:$cellValue") } } } }
2.3 Java实现示例
// 发起接口请求 Request request = new Request.Builder() .url("你的业务接口地址") .addHeader("Accept", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") .build(); new OkHttpClient().newCall(request).enqueue(new Callback() { @Override public void onFailure(@NotNull Call call, @NotNull IOException e) { // 自定义请求失败处理逻辑 } @Override public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { if (!response.isSuccessful()) return; InputStream inputStream = response.body().byteStream(); // 写入本地缓存文件 File excelFile = new File(getCacheDir(), "temp_excel.xlsx"); FileOutputStream outputStream = new FileOutputStream(excelFile); byte[] buffer = new byte[4096]; int len; while ((len = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } outputStream.close(); inputStream.close(); // 解析Excel内容 parseExcelContent(excelFile); } }); // 解析Excel方法 private void parseExcelContent(File file) { try { ExcelWorkbook workbook = new ExcelWorkbook(file); Sheet sheet = workbook.getSheet(0); if (sheet == null) return; for (int rowIndex = 0; rowIndex < sheet.getRows().size(); rowIndex++) { Row row = sheet.getRows().get(rowIndex); for (int cellIndex = 0; cellIndex < row.getCells().size(); cellIndex++) { Cell cell = row.getCells().get(cellIndex); Object cellValue = cell.getValue(); // 按业务需求填充到UI控件 Log.d("Excel数据", "第" + (rowIndex+1) + "行第" + (cellIndex+1) + "列:" + cellValue); } } } catch (IOException e) { e.printStackTrace(); } }
注意事项
- 接口请求头的
Accept字段要指定为Excel对应的MIME类型,避免接口返回错误格式 - 大文件建议开启分块下载,避免出现OOM异常
- 涉及网络请求和文件读写,需要动态申请
INTERNET、WRITE_EXTERNAL_STORAGE(存储到公共目录时需要)权限 - 解析完成后可删除临时缓存文件,避免占用应用存储空间
内容的提问来源于stack exchange,提问作者Jesse Okoro
相关产品推荐
相关产品推荐

