从Firebase存储获取多个下载URL并将其保存到Firebase Firestore

时间:2019-05-15 14:38:12

标签: android firebase hashmap google-cloud-firestore firebase-storage

我已成功将多个选定的音频文件上传到Firebase存储,并且能够检索所有这些文件的URL。由于我必须上传多个文件,因此我使用了循环功能。上传文件并检索URL后,我想将它们保存到Firestore,这就是我要做的事情。

上传文件的功能

private void Button1_Click(object sender, EventArgs e)
{

        SqlConnection con = new SqlConnection();
        con.ConnectionString = "**Data Source=ARSHAD\\SQLEXPRESS;Initial Catalog=softcode;Persist Security Info=True;User ID=sa;Password=***********"**;
        **con.Open();**
        string username = TxtUser.Text;
        string password = TxtPass.Text;
        SqlCommand cmd = new SqlCommand("select username,password from login where username='" + TxtUser.Text + "'and password='" + TxtPass.Text + "'", con);
        SqlDataAdapter da = new SqlDataAdapter(cmd);
        DataTable dt = new DataTable();
        da.Fill(dt);
        if (dt.Rows.Count > 0)
        {
            MessageBox.Show("ok working !!! , set path to open the main window");

        }
        else
        {
            MessageBox.Show("Invalid Login please check username and password");
        }
        con.Close();
}

在保存按钮上单击

下面是调用uploadAudioFiles()函数的代码。

private void uploadAudioFiles(List<Uri> list, final Map<String, String> hashMap) {
        if (list.size() > 0){
            for (int a=0; a<list.size(); a++){
                Uri perFile = list.get(a);
                String filename = getSelectedFileName(perFile);
                final StorageReference audioFileReference = referenceFolder.child("audioClipData/"+filename);
                final int finalA = a;
                audioFileReference.putFile(perFile).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        audioFileReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                            @Override
                            public void onSuccess(Uri uri) {
                                hashMap.put("audioFile"+ finalA, String.valueOf(uri));
                                Log.e("APP_LOG:HashMap(AudioA)", String.valueOf(hashMap));
                            }
                        });
                    }
                });
            }
        }
    }

这是我在uploadAudioFiles()函数中获取的日志

  

E / APP_LOG:HashMap(AudioA):{username = Abhi,   audioFile0 = {https://firebasestorage.googleapis.com/v0/b/myapp.appspot.com/o/linktofile}

这是当我不在uploadAudioFiles()(ButtonClick)函数之外时得到的日志

  

E / APP_LOG:HashMapFINAL:{username = Abhi}

现在,当我处于上载文件功能时以及当我不在上载文件功能中时,我不明白为什么HashMap会有所不同。这是因为for循环的范围还是其他原因?

有人可以帮助我了解情况和解决方案吗?

2 个答案:

答案 0 :(得分:0)

Firebase API是异步的,并且在工作完成之前立即返回。每当上传完成并知道下载URL时,您的HashMap都会随着时间变化。如果您想知道所有上传的完成时间和所有下载URL的已知时间,则需要注意所有它们返回的Task对象。现在,您的uploadAudioFiles函数将在任何工作完成之前立即返回,并且在此之后运行的代码要等一段时间后才能看到任何结果。

答案 1 :(得分:0)

这是执行我想要的新代码!

private void executeUpload(final Map<String, String> hashMap, final List<Uri> uriList) {
        if (uriList.size() > 0){
            spotDialog.show();
                int counter = 0;
                final String firebasePushID = firestore.collection(currentUser.getUid()).document().getId();
                for (int i=0;i<uriList.size(); i++){
                    Uri perFile = uriList.get(i);
                    counter++;
                    final int finalCounter = counter;
                    final int finalI = i;
                    storageReference.child(firebasePushID).putFile(perFile).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
                        @Override
                        public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {
                            if (task.isSuccessful()){
                                storageReference.child(firebasePushID).getDownloadUrl().addOnCompleteListener(new OnCompleteListener<Uri>() {
                                    @Override
                                    public void onComplete(@NonNull Task<Uri> task) {
                                        if (task.isSuccessful()){
                                            String uri = String.valueOf(task.getResult());
                                            Log.e(LOGCODE, uri);
                                            hashMap.put(fileName, uri);
                                            if (!(finalCounter < uriList.size())){
                                                firestore.collection(currentUser.getUid()).add(hashMap).addOnCompleteListener(new OnCompleteListener<DocumentReference>() {
                                                    @Override
                                                    public void onComplete(@NonNull Task<DocumentReference> task) {
                                                        if (task.isSuccessful()){
                                                            clearFormData();
                                                            spotDialog.dismiss();
                                                            Log.e(LOGCODE, hashMap.toString());
                                                            Toast.makeText(MainActivity.this, "Saved data successfully.", Toast.LENGTH_SHORT).show();
                                                        }else {
                                                            Log.e(LOGCODE, Objects.requireNonNull(task.getException()).getMessage());
                                                            spotDialog.dismiss();
                                                            Toast.makeText(MainActivity.this, "Couldn't save data! Data seems to be lost in space :(", Toast.LENGTH_SHORT).show();
                                                        }
                                                    }
                                                });
                                            }
                                        }else {
                                            spotDialog.dismiss();
                                            Log.e(LOGCODE, Objects.requireNonNull(task.getException()).getMessage());
                                            Toast.makeText(MainActivity.this," File uploaded but lost in space :(", Toast.LENGTH_SHORT).show();
                                        }
                                    }
                                });
                            }else{
                                spotDialog.dismiss();
                                Log.e(LOGCODE, Objects.requireNonNull(task.getException()).getMessage());
                                Toast.makeText(AddTransaction.this, "Couldn't upload file ", Toast.LENGTH_SHORT).show();
                            }
                        }
                    });
                }
        }
    }

我想做什么?

首先,将用户名添加到哈希图中,然后上传AudioFiles,然后将这些文件的URL存储到哈希图中,然后将其保存到firestore。

旧代码有问题吗?

编写旧代码是将audioFiles存储到FirebaseStorage,然后将其URL存储到Firestore,但是不幸的是,使用旧代码,这没有发生。

问题背后的原因:-firebase API是异步的,并且要使所有内容按顺序正常工作,我必须等到所有文件上传完毕并将其URL保存到哈希图中。由于我的代码未编写为等待任何内容,因此它只是调用“ uploadAudioFiles”函数,然后不等待响应就使用它来到达函数结尾。这就是我的哈希表为空的原因。直到我尝试将哈希图保存到Firestore时才上传文件,因此哈希图为空。

我如何解决我的问题?

在旧代码中,我正在调用uploadAudioFunction,该函数曾用于将文件上传到FirebaseStorage,但并未编写将哈希图保存到firestore的功能。因此,我基本上重新编写了处理文件上传以及将哈希映射保存到Firestore的函数。我使用了一个计数器变量来计数for循环是否已旋转到列表末尾。使用该计数器变量,我编写了一个if ... else条件,该条件表明循环是否旋转了所需的时间,然后将哈希图数据保存到firestore中。这样,我就可以等到所有文件上传完毕并将其URL保存到哈希图中。

  

警告:-这不是最好的方法。有时哈希图不   包含最后一个文件URL,但文件已成功上传。这是我目前所获得的一切,但我仍在尝试寻找一种新的有效方法来完成此任务。如果您有更好的方法,请告诉我。