英文:
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 && resultCode == RESULT_OK) {
final String folderName = intent.getStringExtra("folderName");
if (data.getClipData() != null) {
//multiple files
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, "File Uploaded!", 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: Task was successful");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.d("TEST", "onFailure: Task was not successful" +
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()); //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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论