Problem in uploading url of mutiple files to Firestore – Android

huangapple go评论39阅读模式
英文:

Problem in uploading url of mutiple files to Firestore - Android

问题

我正在尝试使用for循环将多个文件上传到Firebase存储并将它们的URL添加到Firestore。如果我尝试上传3个文件,那么所有3个文件都会上传到Firebase存储,但只有第一个文件的URL被添加到Firestore。我认为for循环本身没有问题,那么应该如何修复这个问题?

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

    if (requestCode == 101 && resultCode == RESULT_OK) {

        final String folderName = intent.getStringExtra("folderName");

        if (data.getClipData() != null) {
            // 多个文件

            int numItemSelected = data.getClipData().getItemCount();

            for (int i = 0; i < numItemSelected; i++) {

                Uri pdfUri = data.getClipData().getItemAt(i).getUri();
                fileName = getFileName(pdfUri);

                pdfNameList.add(fileName);
                pdfUrlList.add(pdfUri.toString());

                StorageReference pdfRef = storageReference.child(folderName + "/" + fileName);
                pdfRef.putFile(pdfUri)
                    .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                        @Override
                        public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                            Toast.makeText(MainActivity.this, "文件已上传!", Toast.LENGTH_SHORT).show();

                            Task<Uri> uriTask = taskSnapshot.getStorage().getDownloadUrl();
                            while (!uriTask.isComplete());
                            Uri uri = uriTask.getResult();

                            Map<String, Object> map = new HashMap<>();
                            map.put("url", String.valueOf(uri));
                            map.put("name", fileName);
                            DocumentReference documentReference =
                                db.collection(folderName).document(fileName);

                            documentReference.set(map)
                                .addOnSuccessListener(new OnSuccessListener<Void>() {
                                    @Override
                                    public void onSuccess(Void aVoid) {
                                        Log.d("TEST", "onSuccess: 任务成功");

                                    }
                                })
                                .addOnFailureListener(new OnFailureListener() {
                                    @Override
                                    public void onFailure(@NonNull Exception e) {
                                        Log.d("TEST", "onFailure: 任务未成功" +
                                            e.getLocalizedMessage() + "  " + e.getMessage());
                                    }
                                });

                        }
                    })
                    .addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    });
            }
            Log.d("size", "onActivityResult: " + pdfNameList.size()); // 记录正确的大小

        } else if (data.getData() != null) {
            // 选择单个文件
            // 有效的代码,从这里跳过

        }
    }
}

编辑: 只有最后一个文档被上传到Firestore。如果我上传两个文件,那么i(for循环的变量)的值在放入我的映射后为2。

编辑: 我的问题类似于这个问题,但我似乎无法理解解决方案。

英文:

I am trying to upload multiple files to firebase storage and their urls to Firestore using a for loop. If I try to upload 3 files,then all 3 are uploaded to the firebase storage but the url of only the first file is added to Firestore. I don't see any problem in my for loop as such, so how should I fix this?

 @Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 101 &amp;&amp; resultCode == RESULT_OK) {
final String folderName = intent.getStringExtra(&quot;folderName&quot;);
if (data.getClipData() != null) {
//multiple files
int numItemSelected = data.getClipData().getItemCount();
for (int i = 0; i &lt; numItemSelected; i++) {
Uri pdfUri = data.getClipData().getItemAt(i).getUri();
fileName = getFileName(pdfUri);
pdfNameList.add(fileName);
pdfUrlList.add(pdfUri.toString());
StorageReference pdfRef = storageReference.child(folderName + &quot;/&quot; + fileName);
pdfRef.putFile(pdfUri)
.addOnSuccessListener(new OnSuccessListener &lt; UploadTask.TaskSnapshot &gt; () {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(MainActivity.this, &quot;File Uploaded!&quot;, Toast.LENGTH_SHORT).show();
Task &lt; Uri &gt; uriTask = taskSnapshot.getStorage().getDownloadUrl();
while (!uriTask.isComplete());
Uri uri = uriTask.getResult();
Map &lt; String, Object &gt; map = new HashMap &lt; &gt; ();
map.put(&quot;url&quot;, String.valueOf(uri));
map.put(&quot;name&quot;, fileName);
DocumentReference documentReference =
db.collection(folderName).document(fileName);
documentReference.set(map)
.addOnSuccessListener(new OnSuccessListener &lt; Void &gt; () {
@Override
public void onSuccess(Void aVoid) {
Log.d(&quot;TEST&quot;, &quot;onSuccess: Task was  successful&quot;);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.d(&quot;TEST&quot;, &quot;onFailure: Task was not successful&quot; +
e.getLocalizedMessage() + &quot;  &quot; + e.getMessage());
}
});
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
Log.d(&quot;size&quot;, &quot;onActivityResult: &quot; + pdfNameList.size()); //logs the correct size
} else if (data.getData() != null) {
//selected single file
//working code,skipped from here   
}
}
}

Edit : Only the last document is being uploaded to Firestore. If I am uploading two files then the value of i (variable of for loop) is 2 just after putting strings in my map

Edit: My problem is similar to this, but I can't seem to understand the solution

答案1

得分: 0

问题在于您正在以同步方式执行多个连续的异步操作(上传到存储和向Firestore添加数据),这导致了以下行为(示例):

在第一个操作到Firestore完成之前,第二次上传到存储就触发了,这导致了用于Firestore操作的fileName变量被填充为下一个上传的值。

我建议解决您面临的问题的方法要么不按顺序执行操作,例如将所有内容上传到存储,然后再添加到Firestore,要么在filename变量的值被填充后立即填充依赖于该变量的地图部分,而不是在onSuccess处理程序中填充。

英文:

The problem is that you are doing multiple sequenced asynchronous operations (upload to Storage and adding data to firestore) in a synchronous way in your loop and that causes the following behavior (example):

The second upload to Storage triggers before the first operation to Firestore has been completed, and this causes the fileName variable that is being used for the Firestore operation to be populated with value of the next upload.

My suggestion to fix the issue you are facing would be to either not do the operations in sequence, eg. upload everything into storage and only then add everything to firestore, or populate the part of your map that depends on the filename variable right after it's value has been populated and not in the onSuccess handler.

huangapple
  • 本文由 发表于 2020年7月23日 06:45:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/63044225.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定