Android上传PDF至Firebase Storage遇PERMISSION DENIED权限错误
Android Firebase Storage PDF上传权限拒绝问题解决
问题背景
尝试将PDF文件上传至Firebase Storage,已参考官方文档修改代码,但在已声明权限、申请并获取运行时授权的情况下,仍抛出PERMISSION DENIED异常。
预期目标
- 目标文件:
mypdf.pdf,位于公共下载目录/storage/emulated/0/downloads - 将该文件上传至Firebase Storage
尝试操作
通过Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + "/mypdf.pdf"获取文件路径,转换为Uri后传入Firebase的putFile()方法执行上传。
onCreate()中权限检查代码
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + "/mypdf.pdf"); if (file.exists()) { uploadFileFromFirebaseTut(); Log.d("FileLog", "onCreate: found the file"); } else Log.d("MainActivity.this", "onCreate: could not find file"); } else ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 81);
文件上传函数
private void uploadFileFromFirebaseTut() { StorageReference storageRef = storage.getReference(); UploadTask uploadTask; Uri file = Uri.fromFile(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/mypdf.pdf")); StorageReference riversRef = storageRef.child("uploads/mypdf.pdf"); uploadTask = riversRef.putFile(file); // 监听上传状态 uploadTask.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception exception) { Log.d("File Upload failed", "onFailure: "+exception); Toast.makeText(MainActivity.this, "File Upload Failed...", Toast.LENGTH_SHORT).show(); } }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { // taskSnapshot.getMetadata()包含文件元数据,如大小、内容类型等 Toast.makeText(MainActivity.this, "File Uploaded..", Toast.LENGTH_SHORT).show(); } }); }
错误日志
An unknown error occurred, please check the HTTP result code and inner exception for server response. Code: -13000 HttpResult: 0 StorageException E /storage/emulated/0/Download/mypdf.pdf: open failed: EACCES (Permission denied) java.io.FileNotFoundException: /storage/emulated/0/Download/mypdf.pdf: open failed: EACCES (Permission denied) at libcore.io.IoBridge.open(IoBridge.java:492) at java.io.FileInputStream.<init>(FileInputStream.java:160) at java.io.FileInputStream.<init>(FileInputStream.java:115) at android.content.ContentResolver.openInputStream(ContentResolver.java:1484) at com.google.firebase.storage.UploadTask.<init>(UploadTask.java:152) at com.google.firebase.storage.StorageReference.putFile(StorageReference.java:241) at com.example.firebaseupload.MainActivity.uploadFileFromFirebaseTut(MainActivity.java:84) at com.example.firebaseupload.MainActivity.onCreate(MainActivity.java:55) at android.app.Activity.performCreate(Activity.java:8153) at android.app.Activity.performCreate(Activity.java:8137) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1310) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3698) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3896) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:140) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:100) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2326) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:263) at android.app.ActivityThread.main(ActivityThread.java:8296) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006) Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied) at libcore.io.Linux.open(Native Method) at libcore.io.ForwardingOs.open(ForwardingOs.java:166) at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254) at libcore.io.ForwardingOs.open(ForwardingOs.java:166) at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8178) at libcore.io.IoBridge.open(IoBridge.java:478) at java.io.FileInputStream.<init>(FileInputStream.java:160) at java.io.FileInputStream.<init>(FileInputStream.java:115) at android.content.ContentResolver.openInputStream(ContentResolver.java:1484) at com.google.firebase.storage.UploadTask.<init>(UploadTask.java:152) at com.google.firebase.storage.StorageReference.putFile(StorageReference.java:241) at com.example.firebaseupload.MainActivity.uploadFileFromFirebaseTut(MainActivity.java:84) at com.example.firebaseupload.MainActivity.onCreate(MainActivity.java:55) at android.app.Activity.performCreate(Activity.java:8153) at android.app.Activity.performCreate(Activity.java:8137) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1310) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3698) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3896) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:140) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:100) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2326) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:263) at android.app.ActivityThread.main(ActivityThread.java:8296) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006) StorageException E StorageException has occurred.
Manifest声明的权限
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
解决方案
1. 适配Android 10+分区存储规则
从Android 10(API 29)开始,READ_EXTERNAL_STORAGE无法直接访问公共目录文件,需采用以下两种方式:
方式一:通过MediaStore获取Content Uri
改用系统MediaStore查询下载目录中的文件,获取可访问的Content Uri:
// 查询下载目录中的mypdf.pdf String[] projection = {MediaStore.Files.FileColumns._ID}; String selection = MediaStore.Files.FileColumns.DISPLAY_NAME + " = ?"; String[] selectionArgs = {"mypdf.pdf"}; Uri contentUri = MediaStore.Downloads.EXTERNAL_CONTENT_URI; Cursor cursor = getContentResolver().query(contentUri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)); Uri fileUri = ContentUris.withAppendedId(contentUri, id); // 使用该Uri调用putFile上传 uploadFileWithContentUri(fileUri); cursor.close(); }
方式二:申请MANAGE_EXTERNAL_STORAGE权限(Android 11+)
若需直接操作公共目录,在Android 11及以上需申请全存储访问权限:
- 添加Manifest权限:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:minSdkVersion="30"/>
- 运行时请求权限:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (!Environment.isExternalStorageManager()) { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivity(intent); } }
2. 检查Firebase Storage安全规则
确保Storage规则允许上传操作,测试阶段可临时设置为公开规则(上线后需修改为严格权限):
rules_version = '2'; service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { allow read, write: if request.auth == null; // 仅测试用,上线后删除 } } }
3. 优化代码冗余
避免在onCreate和上传函数中重复构建File对象,可将文件Uri作为参数传递,减少代码冗余。
内容的提问来源于stack exchange,提问作者Anirudhdhsinh Jadeja
相关产品推荐
相关产品推荐

