如何从Firebase Storage的getDownloadURL中获取URL

42

我正试图获取我们 Firebase 存储桶中文件的“长期持久下载链接”。 我已更改其权限为

service firebase.storage {
  match /b/project-xxx.appspot.com/o {
    match /{allPaths=**} {
      allow read, write;
    }
  }
}

我的Java代码如下:

private String niceLink (String date){
    String link;
    // Points to the root reference
    StorageReference storageRef = FirebaseStorage.getInstance().getReference();
    StorageReference dateRef = storageRef.child("/" + date+ ".csv");
    link = dateRef.getDownloadUrl().toString();
    return link;
}

当我运行此代码时,我得到一个URI链接,看起来像是com.google.android.gms.tasks.zzh@xxx

问题1. 我能否从中获取类似于以下的下载链接:https://firebasestorage.googleapis.com/v0/b/project-xxxx.appspot.com/o/20-5-2016.csv?alt=media&token=b5d45a7f-3ab7-4f9b-b661-3a2187adxxxx

尝试获取上述链接时,我更改了返回前的最后一行结果如下:

private String niceLink (String date){
    String link;
    // Points to the root reference
    StorageReference storageRef = FirebaseStorage.getInstance().getReference();
    StorageReference dateRef = storageRef.child("/" + date+ ".csv");
    link = dateRef.getDownloadUrl().getResult().toString();
    return link;
}

但是当我这样做时,我收到了403错误,并且应用程序崩溃。控制台告诉我,这是因为用户没有登录/认证。"请在请求令牌之前登录"

问题2:我该如何解决这个问题?


这篇文章和这个仓库肯定会有所帮助。 - Alex Mamo
14个回答

41
请参考文档以获取下载URL
当您调用getDownloadUrl()时,调用是异步的,您必须订阅成功回调才能获得结果:
// Calls the server to securely obtain an unguessable download Url
private void getUrlAsync (String date){
    // Points to the root reference
    StorageReference storageRef = FirebaseStorage.getInstance().getReference();
    StorageReference dateRef = storageRef.child("/" + date+ ".csv");
    dateRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>()
    {
        @Override
        public void onSuccess(Uri downloadUrl) 
        {                
           //do something with downloadurl
        } 
    });
}

这将返回一个公共的不可猜测的下载链接。如果您刚刚上传了文件,这个公共链接将在上传成功回调中(无需在上传后再调用另一个异步方法)。

但是,如果您只想要引用的字符串表示形式,可以直接调用.toString()方法。

// Returns a Uri of the form gs://bucket/path that can be used
// in future calls to getReferenceFromUrl to perform additional
// actions
private String niceRefLink (String date){
    // Points to the root reference
    StorageReference storageRef = FirebaseStorage.getInstance().getReference();
    StorageReference dateRef = storageRef.child("/" + date+ ".csv");
    return dateRef.toString();
}

1
使用Async时,我似乎在.addSuccessListener(无法解析方法)中遇到了错误。 此外,在onSuccess方法中使用类似link = downloadUrl.toString()的东西时,它说需要是final。 任何进一步的帮助都将非常棒! - Jonathan Fager
1
  1. 抱歉,应该是addOnSuccessListener(笔误)。
  2. 当你在Java中遇到“需要是final”的错误时,这意味着存在闭包问题。请参见https://dev59.com/2HM_5IYBdhLWcg3wn0lO了解更多信息。基本上,简短的答案是将“link”变量定义为类成员,就可以解决问题了。
- Benjamin Wulfe
1
经过一些编辑后,工作得非常好!感谢您的帮助! - Jonathan Fager
顺便提一下,任何"无法猜测的下载链接"仍然是一个公共链接,可以绕过任何访问规则,并且任何获得该链接的人都可以访问。 - undefined

9
//Firebase Storage - 简单易用的上传和下载服务。
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable final Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode == RC_SIGN_IN){
        if(resultCode == RESULT_OK){
            Toast.makeText(this,"Signed in!", LENGTH_SHORT).show();
        } else if(resultCode == RESULT_CANCELED){
            Toast.makeText(this,"Signed in canceled!", LENGTH_SHORT).show();
            finish();
        }
    } else if(requestCode == RC_PHOTO_PICKER && resultCode == RESULT_OK){

        // HERE I CALLED THAT METHOD
        uploadPhotoInFirebase(data);

    }
}

private void uploadPhotoInFirebase(@Nullable Intent data) {
    Uri selectedImageUri = data.getData();

    // Get a reference to store file at chat_photos/<FILENAME>
    final StorageReference photoRef = mChatPhotoStorageReference
                    .child(selectedImageUri
                    .getLastPathSegment());

    // Upload file to Firebase Storage
    photoRef.putFile(selectedImageUri)
            .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {

                    // Download file From Firebase Storage
                    photoRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                        @Override
                        public void onSuccess(Uri downloadPhotoUrl) {
                            //Now play with downloadPhotoUrl
                            //Store data into Firebase Realtime Database
                            FriendlyMessage friendlyMessage = new FriendlyMessage
                                    (null, mUsername, downloadPhotoUrl.toString());
                            mDatabaseReference.push().setValue(friendlyMessage);
                        }
                    });
                }
            });
}

6

我正在同时上传和获取图片的URL...

           final StorageReference profileImageRef = FirebaseStorage.getInstance().getReference("profilepics/" + System.currentTimeMillis() + ".jpg");

            if (uriProfileImage != null) {

            profileImageRef.putFile(uriProfileImage)
                        .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                            @Override
                            public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                               // profileImageUrl taskSnapshot.getDownloadUrl().toString(); //this is depreciated

                          //this is the new way to do it
                   profileImageRef.getDownloadUrl().addOnCompleteListener(new OnCompleteListener<Uri>() {
                                    @Override
                                    public void onComplete(@NonNull Task<Uri> task) {
                                       String profileImageUrl=task.getResult().toString();
                                        Log.i("URL",profileImageUrl);
                                    }
                                });
                            }
                        })
                        .addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                progressBar.setVisibility(View.GONE);
                                Toast.makeText(ProfileActivity.this, "aaa "+e.getMessage(), Toast.LENGTH_SHORT).show();
                            }
                        });
            }

你能否使用Glide库将此URL用于向用户展示图片? - Shubham Garg

3

对于我而言,我使用 Kotlin 编写了代码,遇到了相同的错误 "getDownload()"。以下是对我有效的依赖项和 Kotlin 代码。

implementation 'com.google.firebase:firebase-storage:18.1.0' Firebase 存储依赖项

这是我添加的 Kotlin 代码,在 Storage() 前面加上 Download() 即可解决问题。

profileImageUri = taskSnapshot.storage.downloadUrl.toString()

1
implementation 'com.google.firebase:firebase-storage:19.2.0'

最近从上传任务获取 URL 不起作用,所以我尝试了这个,在上面的依赖项上为我工作。 因此,在使用 Firebase 上传方法的位置使用此方法。 文件路径是 Firebase 存储的参考。

filePath.putFile(imageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
        filePath.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
            @Override
            public void onSuccess(Uri uri) {
                Log.d(TAG, "onSuccess: uri= "+ uri.toString());
            }
        });
    }
});

1
你可以将图片上传到Firestore,并使用以下函数获取其下载URL:
  Future<String> uploadPic(File _image) async {

    String fileName = basename(_image.path);
    StorageReference firebaseStorageRef = FirebaseStorage.instance.ref().child(fileName);
    StorageUploadTask uploadTask = firebaseStorageRef.putFile(_image);
    var downloadURL = await(await uploadTask.onComplete).ref.getDownloadURL();
    var url =downloadURL.toString();

   return url;

  }

0

在新的Firebase更新中,getDownloadUrl方法已被弃用。请改用以下方法:taskSnapshot.getMetadata().getReference().getDownloadUrl().toString()


输出类似于 com.google.android.gms.tasks.zzu@ed93411 的内容。 - Pranjal Choladhara

0

在Firebase版本大于11.0.5中,getDownloadUrl方法已被移除。 我建议使用仍然使用此方法的11.0.2版本。


0

firebase.storage().ref(/users/${userUID}${path}/${newPostKey}) .getDownloadURL() .then(url => object.imageUrl = url)

firebase.storage().ref(/users/${userUID}${path}/${newPostKey}) .getDownloadURL() .then(url => object.imageUrl = url)


目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

0
StorageReference mStorageRef = FirebaseStorage.getInstance().getReference();

final   StorageReference fileupload=mStorageRef.child("Photos").child(fileUri.getLastPathSegment());
UploadTask uploadTask = fileupload.putFile(fileUri);

Task<Uri> urlTask = uploadTask.continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
    @Override
    public Task<Uri> then(@NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
        if (!task.isSuccessful()) {
            throw task.getException();
        }
        return ref.getDownloadUrl();

    }
    }).addOnCompleteListener(new OnCompleteListener<Uri>() {
        @Override
        public void onComplete(@NonNull Task<Uri> task) {
            if (task.isSuccessful()) {
                Uri downloadUri = task.getResult();
                Picasso.get().load(downloadUri.toString()).into(image);

            } else {
                 // Handle failures
            }
       }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接