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

如何将bytearray转为PDF并通过ACTION_VIEW intent打开,解决文件损坏问题

PDF文件损坏问题修复方案

核心问题排查及修复步骤:

  • 1. 清理Base64字符串前缀
    绝大多数损坏是因为传入的Base64串携带了Data URI协议前缀(比如data:application/pdf;base64,),直接解码会将前缀内容也写入PDF文件导致损坏。解码前先清理前缀:

    val cleanBase64 = base64String.substringAfterLast(",", base64String)
    val byteArray = Base64.decode(cleanBase64, Base64.DEFAULT)
    // 可增加校验:正常PDF文件至少几百字节,解码后长度过短直接判定解码失败
    if (byteArray.size < 100) {
        // 抛出异常或提示数据错误
        return
    }
    
  • 2. 给第三方应用授予文件读取权限
    你当前的Intent只配置了FLAG_ACTIVITY_NO_HISTORY,没有给跳转的PDF阅读器授予你FileProvider提供的URI的读取权限,第三方应用读取不到完整文件内容就会提示损坏。补充权限标记:

    val intent = Intent(Intent.ACTION_VIEW)
    intent.setDataAndType(uri, "application/pdf")
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // 必须添加读权限
    intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
    // 可选:校验是否有PDF应用可以处理该Intent,避免崩溃
    if (intent.resolveActivity(requireContext().packageManager) != null) {
        startActivity(intent)
    } else {
        // 提示用户安装PDF阅读器
    }
    
  • 3. 优化文件写入逻辑
    你当前手动关闭流的方式如果中间发生异常会导致流未正常关闭、文件写入不完整。使用Kotlin的use扩展自动管理流的关闭,避免IO异常导致的文件损坏:

    FileOutputStream(file).use { fos ->
        fos.write(byteArray)
    }
    
  • 4. 修正文件创建逻辑
    原有createFile方法中使用的Environment.getExternalStorageDirectory()在Android 10及以上系统已经废弃,直接写入会有权限限制,同时可能出现MimeTypeMap无法正确映射PDF后缀的问题,优化后的实现:

    fun createFile(context: Context, mimeType: String): File {
        val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
        val fileName = "TMP_${timeStamp}_"
        // 兜底PDF后缀,避免MimeType映射失败
        val suffix = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType)?.let { ".$it" } ?: ".pdf"
        // 优先使用App私有缓存目录,不需要申请存储权限,FileProvider可正常访问
        val docDir = File(context.cacheDir, "Documents").apply {
            if (!exists()) mkdirs()
        }
        return File.createTempFile(fileName, suffix, docDir)
    }
    
  • 5. 校验FileProvider配置
    检查你项目中res/xml/file_paths.xml的配置,确保你存储文件的目录已经被正确声明:
    如果你用了上面优化后的缓存目录,需要添加:

    <cache-path name="cache_docs" path="Documents/" />
    

    如果你仍用原有getExternalFilesDir存储,需要添加:

    <external-files-path name="external_docs" path="Documents/" />
    

内容的提问来源于stack exchange,提问作者Mehdi Satei

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 22:54:07