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

使用Retrofit上传PDF及图片文件,如何从URI获取PDF绝对路径

解决方案

无需获取PDF的绝对路径即可完成上传,Android 4.4及以上版本从系统文件选择器拿到的URI多为content://类型,通过ContentResolver直接读取文件流即可,不需要转换为本地真实路径。

步骤1:处理PDF选择返回结果,读取文件内容

在onActivityResult回调中处理选择PDF的返回结果,直接从URI读取PDF字节数组、获取文件名:

// 自定义的PDF选择请求码
private static final int SELECT_PDF = 1002;

if (requestCode == SELECT_PDF) {
    List<byte[]> pdfDataList = new ArrayList<>();
    List<String> pdfFileNameList = new ArrayList<>();
    // 单选PDF场景
    if (data.getData() != null) {
        Uri pdfUri = data.getData();
        try {
            InputStream inputStream = getActivity().getContentResolver().openInputStream(pdfUri);
            byte[] pdfBytes = getBytesFromInputStream(inputStream);
            pdfDataList.add(pdfBytes);
            pdfFileNameList.add(getFileNameFromUri(pdfUri));
        } catch (Exception e) {
            e.printStackTrace();
        }
    } 
    // 多选PDF场景
    else if (data.getClipData() != null) {
        int count = data.getClipData().getItemCount();
        for (int i = 0; i < count; i++) {
            Uri pdfUri = data.getClipData().getItemAt(i).getUri();
            try {
                InputStream inputStream = getActivity().getContentResolver().openInputStream(pdfUri);
                byte[] pdfBytes = getBytesFromInputStream(inputStream);
                pdfDataList.add(pdfBytes);
                pdfFileNameList.add(getFileNameFromUri(pdfUri));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    // 调用上传方法
    uploadPdf(pdfDataList, pdfFileNameList);
}

步骤2:添加工具方法

添加两个通用工具方法,分别实现输入流转字节数组、从URI获取文件名:

// 输入流转字节数组
private byte[] getBytesFromInputStream(InputStream inputStream) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int len;
    while ((len = inputStream.read(buffer)) != -1) {
        baos.write(buffer, 0, len);
    }
    inputStream.close();
    return baos.toByteArray();
}

// 从URI获取文件名,无需读真实路径
private String getFileNameFromUri(Uri uri) {
    String fileName = "unnamed.pdf";
    Cursor cursor = getActivity().getContentResolver().query(uri, null, null, null, null);
    if (cursor != null && cursor.moveToFirst()) {
        int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
        fileName = cursor.getString(nameIndex);
        cursor.close();
    }
    return fileName;
}

步骤3:实现PDF上传逻辑

参考你已有的图片上传逻辑,调整MediaType和表单字段即可:

首先定义API接口(如果后端有单独的PDF上传接口,也可以直接复用你现有上传接口,只要后端支持)

@Multipart
@POST("/api/pdf/upload")
Call<UploadResponse> uploadPdf(@Header("x-auth-token") String authHeader, @Part List<MultipartBody.Part> pdfParts);

上传方法实现

private void uploadPdf(List<byte[]> pdfDataList, List<String> fileNameList) {
    MultipartBody.Part[] parts = new MultipartBody.Part[pdfDataList.size()];
    for (int i = 0; i < pdfDataList.size(); i++) {
        // 修改MediaType为PDF类型
        RequestBody requestFile = RequestBody.create(MediaType.parse("application/pdf"), pdfDataList.get(i));
        String fileName = fileNameList.get(i);
        // 表单字段名需和后端约定一致,此处示例为pdf
        MultipartBody.Part body = MultipartBody.Part.createFormData("pdf", fileName, requestFile);
        parts[i] = body;
    }
    String token = sessionCache.getToken();
    Call<UploadResponse> call = apiInterface.uploadPdf(token, Arrays.asList(parts));
    
    call.enqueue(new Callback<UploadResponse>() {
        @Override
        public void onResponse(Call<UploadResponse> call, Response<UploadResponse> response) {
            Toast.makeText(getContext(), "PDF上传成功", Toast.LENGTH_LONG).show();
            // 处理返回的文件路径等逻辑
        }

        @Override
        public void onFailure(Call<UploadResponse> call, Throwable t) {
            // 处理上传失败逻辑
        }
    });
}

注意事项

  • 通过系统文件选择器获取的URI,应用有临时访问权限,不需要额外申请存储权限即可读取内容
  • 如果后端接口同时支持上传图片和PDF,可将两类文件的MultipartBody.Part合并到同一个列表中,一次请求完成上传
  • Android 13及以上版本如果需要扫描本地PDF列表,需申请READ_MEDIA_DOCUMENTS权限,通过选择器选择文件无需额外权限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 17:54:02