You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Kotlin导出Firebase数据至XLSX无反应且找不到文件求助

问题描述

使用Kotlin结合Apache POI库将Firebase数据库中的数据导出为XLSX文件,程序运行无报错,但无法找到导出的文件。

代码示例

val db =  FirebaseDatabase.getInstance().getReference("aktivitas")
btndownload.setOnClickListener{
    val query_kegiatan = db.orderByChild("aktivitas")

    query_kegiatan.addValueEventListener(object : ValueEventListener{
        override fun onDataChange(snapshot: DataSnapshot) {
            val workbook = XSSFWorkbook()
            val sheet = workbook.createSheet("Aktivitas")

            var rownum = 0
            for(item in snapshot.children){
                val row = sheet.createRow(rownum++)
                row.createCell(0).setCellValue(item.child("bagian").value as String)
                row.createCell(1).setCellValue(item.child("barang").value as String)
                row.createCell(2).setCellValue(item.child("jumlah").value as String)
                row.createCell(3).setCellValue(item.child("keterangan").value as String)

               val save = File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),"aktivitas.xlsx")
                val fos = FileOutputStream(save)
                workbook.write(fos)

            }
        }

        override fun onCancelled(error: DatabaseError) {
            TODO("Not yet implemented")
        }
    })

} 

预期目标:成功将Firebase中的数据导出至XLSX文件。


解决方案

1. 修正文件写入逻辑(核心问题)

你把workbook.write(fos)放在了遍历数据的for循环内部,会导致每次处理一条数据就重复写入文件,不仅效率低下,还可能因文件流未正确关闭导致文件损坏或无法生成。需将文件写入代码移到循环外部,并自动管理流资源:

override fun onDataChange(snapshot: DataSnapshot) {
    val workbook = XSSFWorkbook()
    val sheet = workbook.createSheet("Aktivitas")

    var rownum = 0
    for(item in snapshot.children){
        val row = sheet.createRow(rownum++)
        row.createCell(0).setCellValue(item.child("bagian").value as String)
        row.createCell(1).setCellValue(item.child("barang").value as String)
        row.createCell(2).setCellValue(item.child("jumlah").value as String)
        row.createCell(3).setCellValue(item.child("keterangan").value as String)
    }
    // 循环结束后统一写入文件
    val save = File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),"aktivitas.xlsx")
    FileOutputStream(save).use { fos ->
        workbook.write(fos)
    }
    workbook.close()
}

use函数会自动关闭文件流,避免资源泄漏,最后关闭workbook释放内存。

2. 明确文件存储路径

当前使用的context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)是应用私有存储目录,路径为/storage/emulated/0/Android/data/[你的应用包名]/files/Download/aktivitas.xlsx,系统默认“下载”文件夹不会显示这里的文件。

  • 若想导出到公共下载目录,需先在AndroidManifest.xml添加权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" android:minSdkVersion="33"/>
  • 动态申请权限(Android 6.0+)后,修改路径:
val publicDownloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val save = File(publicDownloadDir, "aktivitas.xlsx")

注意:Android 13+对公共存储权限限制更严格,优先推荐使用应用私有目录,或改用MediaStore API写入公共目录。

3. 替换监听事件类型

addValueEventListener会持续监听数据变化,每次数据更新都会触发导出,应改用addListenerForSingleValueEvent,仅执行一次数据读取和导出:

query_kegiatan.addListenerForSingleValueEvent(object : ValueEventListener{
    // 其余逻辑不变
})

4. 处理空值与异常

避免强制类型转换as String导致的潜在崩溃,同时捕获IO异常并给出提示:

// 安全获取字符串值,空值时用空字符串替代
row.createCell(0).setCellValue(item.child("bagian").value?.toString() ?: "")
row.createCell(1).setCellValue(item.child("barang").value?.toString() ?: "")
row.createCell(2).setCellValue(item.child("jumlah").value?.toString() ?: "")
row.createCell(3).setCellValue(item.child("keterangan").value?.toString() ?: "")

// 捕获IO异常并提示结果
try {
    FileOutputStream(save).use { fos ->
        workbook.write(fos)
    }
    workbook.close()
    Toast.makeText(context, "导出成功", Toast.LENGTH_SHORT).show()
} catch (e: IOException) {
    e.printStackTrace()
    Toast.makeText(context, "导出失败: ${e.message}", Toast.LENGTH_SHORT).show()
}

内容的提问来源于stack exchange,提问作者daffa Firmansyah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 17:45:46