Android Studio中Firebase多图上传问题:下载URL重复
解决Firebase上传多张图片时URL重复的问题
嘿,我一眼就看出问题所在了——你的代码里只真正上传了第一张图片,另外两张连Firebase Storage都没传进去,最后还把第一张的下载URL重复赋值给了三个字段,自然第二、三张的URL和第一张一模一样。下面我给你修正代码,同时解释关键的修改点:
问题根源分析
- 在
startPosting()方法中,你只执行了第一张图片的上传操作filepath.putFile(mImageUri),filepath1和filepath2对应的上传逻辑完全没触发 - 你直接把第一张图的
downloadurl同时赋值给了image、image1、image2三个数据库字段,导致URL重复 - 上传条件只检查了
mImageUri != null,没验证另外两张图片的URI是否有效
修正后的完整Java代码
package ke.co.tapeli.tapeli; import android.app.ProgressDialog; import android.content.Intent; import android.net.Uri; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; import android.widget.Toast; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.OnSuccessListener; import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.Tasks; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseAuth.AuthStateListener; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.storage.FirebaseStorage; import com.google.firebase.storage.StorageReference; import com.google.firebase.storage.UploadTask; import ke.co.tapeli.tapeli.Auths.Login; public class UploadActivity extends AppCompatActivity { private ImageButton mSelectImage; private ImageButton mSelectImage1; private ImageButton mSelectImage2; private EditText mPostTitle; private EditText mPostDesc; private EditText mPostNumber; private EditText mPostPass; private EditText mPostInfo; private EditText mPostSteps; private EditText mPostPolice; private Button mSubmitBtn; private Uri mImageUri = null; private Uri mImageUri1 = null; private Uri mImageUri2 = null; private StorageReference mStorage; private DatabaseReference mDatabase; private ProgressDialog mProgress; private static final int GALLERY_REQUEST = 1; private static final int GALLERY_REQUEST2 = 2; private static final int GALLERY_REQUEST3 = 3; private FirebaseAuth mAuth; private AuthStateListener mAuthListner; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_upload); mAuth = FirebaseAuth.getInstance(); mAuthListner = new AuthStateListener() { @Override public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { if(firebaseAuth.getCurrentUser() == null){ Intent loginIntent = new Intent(UploadActivity.this, Login.class); loginIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(loginIntent); } } }; mStorage = FirebaseStorage.getInstance().getReference(); mDatabase = FirebaseDatabase.getInstance().getReference().child("Matapeli"); mSelectImage = findViewById(R.id.imageSelect); mSelectImage1 = findViewById(R.id.imageSelect1); mSelectImage2 = findViewById(R.id.imageSelect2); mPostTitle = findViewById(R.id.titleField); mPostDesc = findViewById(R.id.descField); mPostNumber = findViewById(R.id.phoneField); mPostPass = findViewById(R.id.passField); mPostInfo = findViewById(R.id.otherField); mPostSteps = findViewById(R.id.stepsField); mPostPolice = findViewById(R.id.policeField); mProgress = new ProgressDialog(this); mSubmitBtn = findViewById(R.id.submitBtn); mSelectImage.setOnClickListener(view -> { Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT); galleryIntent.setType("image/*"); startActivityForResult(galleryIntent, GALLERY_REQUEST); }); mSelectImage1.setOnClickListener(view -> { Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT); galleryIntent.setType("image/*"); startActivityForResult(galleryIntent, GALLERY_REQUEST2); }); mSelectImage2.setOnClickListener(view -> { Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT); galleryIntent.setType("image/*"); startActivityForResult(galleryIntent, GALLERY_REQUEST3); }); mSubmitBtn.setOnClickListener(view -> startPosting()); } private void startPosting() { mProgress.setMessage("Adding a Tapeli..."); final String title_val = mPostTitle.getText().toString().trim(); final String desc_val = mPostDesc.getText().toString().trim(); final String namba_val = mPostNumber.getText().toString().trim(); final String pass_val = mPostPass.getText().toString().trim(); final String info_val = mPostInfo.getText().toString().trim(); final String steps_val = mPostSteps.getText().toString().trim(); final String police_val = mPostPolice.getText().toString().trim(); // 检查所有必填字段和图片URI是否有效(如果允许部分图片上传,可调整此判断) if(!TextUtils.isEmpty(title_val) && !TextUtils.isEmpty(desc_val) && mImageUri != null && mImageUri1 != null && mImageUri2 != null){ mProgress.show(); // 分别创建三个图片的上传任务 StorageReference filepath = mStorage.child("Blog_Images").child(mImageUri.getLastPathSegment()); StorageReference filepath1 = mStorage.child("Blog_Images").child(mImageUri1.getLastPathSegment()); StorageReference filepath2 = mStorage.child("Blog_Images").child(mImageUri2.getLastPathSegment()); Task<Uri> uploadTask1 = filepath.putFile(mImageUri).continueWithTask(task -> { if (!task.isSuccessful()) { throw task.getException(); } return filepath.getDownloadUrl(); }); Task<Uri> uploadTask2 = filepath1.putFile(mImageUri1).continueWithTask(task -> { if (!task.isSuccessful()) { throw task.getException(); } return filepath1.getDownloadUrl(); }); Task<Uri> uploadTask3 = filepath2.putFile(mImageUri2).continueWithTask(task -> { if (!task.isSuccessful()) { throw task.getException(); } return filepath2.getDownloadUrl(); }); // 等待三个上传任务全部完成 Tasks.whenAll(uploadTask1, uploadTask2, uploadTask3) .addOnCompleteListener(task -> { mProgress.dismiss(); if (task.isSuccessful()) { // 获取三张图片各自的下载URL String imageUrl = uploadTask1.getResult().toString(); String imageUrl1 = uploadTask2.getResult().toString(); String imageUrl2 = uploadTask3.getResult().toString(); // 写入数据库 DatabaseReference newPost = mDatabase.push(); newPost.child("title").setValue(title_val); newPost.child("desc").setValue(desc_val); newPost.child("number").setValue(namba_val); newPost.child("passport").setValue(pass_val); newPost.child("info").setValue(info_val); newPost.child("steps").setValue(steps_val); newPost.child("police").setValue(police_val); newPost.child("image").setValue(imageUrl); newPost.child("image1").setValue(imageUrl1); newPost.child("image2").setValue(imageUrl2); Toast.makeText(UploadActivity.this, "Tapeli added successfully!", Toast.LENGTH_SHORT).show(); finish(); } else { // 处理上传失败的情况 Toast.makeText(UploadActivity.this, "Upload failed: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show(); } }); } else { Toast.makeText(this, "Please fill all required fields and select all images!", Toast.LENGTH_SHORT).show(); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode == GALLERY_REQUEST && resultCode == RESULT_OK){ mImageUri = data.getData(); mSelectImage.setImageURI(mImageUri); } if(requestCode == GALLERY_REQUEST2 && resultCode == RESULT_OK){ mImageUri1 = data.getData(); mSelectImage1.setImageURI(mImageUri1); } if(requestCode == GALLERY_REQUEST3 && resultCode == RESULT_OK){ mImageUri2 = data.getData(); mSelectImage2.setImageURI(mImageUri2); } } @Override protected void onStart() { super.onStart(); mAuth.addAuthStateListener(mAuthListner); } @Override protected void onStop() { super.onStop(); if(mAuthListner != null){ mAuth.removeAuthStateListener(mAuthListner); } } }
关键修改说明
- 完善上传条件检查:现在会验证三张图片的URI都不为空(如果你的需求允许只上传部分图片,可以修改这个判断逻辑)
- 分别启动三张图片的上传任务:用
continueWithTask链式调用,在上传完成后直接获取下载URL - 等待所有上传完成再写入数据库:使用
Tasks.whenAll()来等待三个异步上传任务全部完成,避免因异步操作导致的URL缺失或重复 - 独立赋值URL:将三张图片各自的下载URL分别赋值给
image、image1、image2字段 - 添加异常处理:处理上传失败的情况,给用户友好的提示
- 优化代码风格:把匿名内部类换成Lambda表达式,让代码更简洁(兼容Android API 24+,如果需要兼容更低版本可以改回匿名内部类)
内容的提问来源于stack exchange,提问作者user7810601
相关产品推荐
相关产品推荐

