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

Android端PDF转Base64后反向转换失效问题求助

问题描述

我需要将PDF文件上传至服务器,因此要先把PDF文件转换为BASE64字符串。目前转码流程可正常执行,但将得到的BASE64字符串转回PDF时无法生成正确文件,出现如下图所示的报错。
报错截图

相关代码

文件选择代码

@SuppressLint("NewApi")
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult( requestCode, resultCode, data );

    if (requestCode == PDF_REQ_CODE && resultCode == RESULT_OK && data != null && data.getData() != null) {
        uri = data.getData();
        //String path=data.getData().getPath();
        btnPdfFileChooser.setText( "PDF is Selected" );
        //Toast.makeText(FileUploadActivity.this, uri.toString(), Toast.LENGTH_SHORT).show();
        //InputStream inputStream = c.getContentResolver().openInputStream(path)
        PdfUploadFunction();
    }
}

上传函数(暂未编写服务端接口调用更新数据的逻辑)

private void PdfUploadFunction() {
    // Getting pdf name from EditText.
    PdfNameHolder = strPdfFileName.toString().trim();
    // Getting file path using Filepath class.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        PdfPathHolder = FilePath.getPath( this, uri );
    }
    // If file path object is null then showing toast message to move file into internal storage.
    if (PdfPathHolder == null) {
        Toast.makeText( this, "Please move your PDF file to internal storage & try again.", Toast.LENGTH_LONG ).show();
    }
    // If file path is not null then PDF uploading file process will starts.
    else {
        String base64 = getBase64FromPath( PdfPathHolder );
        //String base64 = encodeFileToBase64Binary( PdfPathHolder );
        Toast.makeText( this, "base64-" + base64, Toast.LENGTH_LONG ).show();
        Log.e( "base64-", base64.toString() );
    }
}

BASE64转码代码

public static String getBase64FromPath(String path) {
      
        byte[] byteArray = null;
        try {
            File file = new File( path );
            InputStream inputStream = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024 * 11];
            int bytesRead = 0;

            while ((bytesRead = inputStream.read(b)) != -1) {
                bos.write(b, 0, bytesRead);
            }

            byteArray = bos.toByteArray();

            Log.e("Byte array", ">" + byteArray);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return Base64.encodeToString(byteArray, Base64.NO_WRAP);
    }
解决方案

核心问题原因

  1. 不要通过FilePath.getPath()获取uri对应的文件路径,Android 10及以上版本的分区存储限制下,通过uri拿到的路径很多时候不可访问,或者拿到的是媒体库的虚拟路径,读取到的文件字节流是错误的。
  2. 转码逻辑没有处理流关闭的问题,小概率会出现字节流读取不完整的情况。
  3. 部分场景下Base64编码参数不合适,如果服务端解码要求带换行或者使用URL_SAFE模式也会出现解码失败,但最核心的问题还是文件路径读取错误。

修复代码

1. 调整文件读取逻辑,直接通过ContentResolver读取uri对应的输入流,不要转成文件路径

修改PdfUploadFunction方法:

private void PdfUploadFunction() {
    PdfNameHolder = strPdfFileName.toString().trim();
    try {
        // 直接通过uri获取输入流,不需要转换为本地路径
        InputStream inputStream = getContentResolver().openInputStream(uri);
        String base64 = getBase64FromInputStream(inputStream);
        Log.e( "base64-", base64 );
        Toast.makeText( this, "base64生成成功", Toast.LENGTH_LONG ).show();
    } catch (Exception e) {
        e.printStackTrace();
        Toast.makeText( this, "文件读取失败,请检查文件权限", Toast.LENGTH_LONG ).show();
    }
}

2. 修改Base64转码方法,直接接收输入流处理,同时补全流关闭逻辑

public static String getBase64FromInputStream(InputStream inputStream) {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    byte[] b = new byte[1024 * 8];
    int bytesRead = 0;
    try {
        while ((bytesRead = inputStream.read(b)) != -1) {
            bos.write(b, 0, bytesRead);
        }
        byte[] byteArray = bos.toByteArray();
        return Base64.encodeToString(byteArray, Base64.NO_WRAP);
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    } finally {
        // 关闭所有流避免资源泄漏
        try {
            inputStream.close();
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

验证方法

生成base64字符串后,可以先在本地做解码验证:将得到的base64字符串解码为字节数组,写入本地存储为新的PDF文件,如果新文件可以正常打开,再调用服务端接口上传。
如果服务端解码仍然失败,确认服务端的解码规则是否和Android端编码规则一致:是否需要Base64.URL_SAFE参数、是否要求去掉base64前缀(如data:application/pdf;base64,)。

内容的提问来源于stack exchange,提问作者Pranav MS

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 13:06:02