我已成功将多个选定的音频文件上传到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循环的范围还是其他原因?
有人可以帮助我了解情况和解决方案吗?
答案 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,但文件已成功上传。这是我目前所获得的一切,但我仍在尝试寻找一种新的有效方法来完成此任务。如果您有更好的方法,请告诉我。