如何在实时 Firebase 数据库中保存上传图像的完美 url 链接?

时间:2021-04-27 11:59:23

标签: java android firebase firebase-realtime-database firebase-storage

我使用以下代码上传图像并将文本和 URL 链接保存到实时 firebase 数据库,但我无法使用保存的 URL 链接访问图像。我在做什么错误?如何在 Firebase 中保存上传图片的完美 URL 链接?

MainActivity.java 的代码

package com.example.project1;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.ContentResolver;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.webkit.MimeTypeMap;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Continuation;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.OnProgressListener;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import com.squareup.picasso.Picasso;

public class MainActivity extends AppCompatActivity {
    private static final int PICK_IMAGE_REQUEST = 1;
    Button mButtonChooseImage;
    EditText mEditTextFileName;
    ImageView mImageView;
    ProgressBar mProgressBar;
    Uri mImageUri;
    Button mButtonUpload;
    StorageReference mStorageRef;
    DatabaseReference mDatabaseRef;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButtonChooseImage = findViewById(R.id.button_choose_image);
        mButtonChooseImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                openFileChooser();
            }
        });
        mEditTextFileName = findViewById(R.id.edit_text_file_name);
        mImageView = findViewById(R.id.image_view);
        mButtonUpload = findViewById(R.id.button_upload);
        mProgressBar = findViewById(R.id.progress_bar);
        mStorageRef = FirebaseStorage.getInstance().getReference("products");
        mDatabaseRef = FirebaseDatabase.getInstance().getReference("products");

        mButtonUpload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                uploadFile();
            }
        });
    }

    private void openFileChooser() {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(intent, PICK_IMAGE_REQUEST);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK
                && data != null && data.getData() != null) {
            mImageUri = data.getData();
            Picasso.with(this).load(mImageUri).into(mImageView);
        }
    }


    private String getFileExtension(Uri uri){
        ContentResolver cR = getContentResolver();
        MimeTypeMap mime = MimeTypeMap.getSingleton();
        return mime.getExtensionFromMimeType(cR.getType(uri));
    }
    //
    private void uploadFile() {
        if (mImageUri != null) {
            StorageReference fileReference = mStorageRef.child(System.currentTimeMillis() + "." + getFileExtension(mImageUri));
            UploadTask uploadTask = fileReference.putFile(mImageUri);
            uploadTask.addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception exception) {
                    // Handle unsuccessful uploads
                    Toast.makeText(MainActivity.this, exception.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                    Handler handler = new Handler();
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mProgressBar.setProgress(0);
                        }
                    }, 500);
                    Toast.makeText(MainActivity.this, "Upload successful", Toast.LENGTH_LONG).show();
                }
            }).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onProgress(@NonNull UploadTask.TaskSnapshot snapshot) {
                    double progress = (100.0 * snapshot.getBytesTransferred()/snapshot.getTotalByteCount());
                    mProgressBar.setProgress((int) progress);
                }
            });
// get download URL
            Task<Uri> urlTask = uploadTask.continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
                @Override
                public Task<Uri> then(@NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
                    if (!task.isSuccessful()) {
                        throw task.getException();
                    }
                    // Continue with the task to get the download URL
                    Task<Uri> url1 = fileReference.getDownloadUrl();
                    Upload upload = new Upload(mEditTextFileName.getText().toString().trim(), url1.toString());
                    String uploadId = mDatabaseRef.push().getKey();
                    mDatabaseRef.child(uploadId).setValue(upload);
//                    Toast.makeText(MainActivity.this, "Url : "+url1, Toast.LENGTH_LONG).show();
                    return fileReference.getDownloadUrl();
                }
            }).addOnCompleteListener(new OnCompleteListener<Uri>() {
                @Override
                public void onComplete(@NonNull Task<Uri> task) {
                    if (task.isSuccessful()) {
                        Uri downloadUri = task.getResult();
                    }
                    else {
                        // Handle failures
                        // ...
                    }
                }
            });

        }
    }
}

Upload.java 的代码:

package com.example.project1;

public class Upload {
    private String mName;
    private String mImageUrl;
    public Upload() {
        //empty constructor needed
    }
    public Upload(String name, String imageUrl) {
        if (name.trim().equals("")) {
            name = "No Name";
        }
        mName = name;
        mImageUrl = imageUrl;
    }
    public String getName() {
        return mName;
    }
    public void setName(String name) {
        mName = name;
    }
    public String getImageUrl() {
        return mImageUrl;
    }
    public void setImageUrl(String imageUrl) {
        mImageUrl = imageUrl;
    }
}

activity_main.xml 的 XML 代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/text_view_show_uploads"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_marginStart="30dp"
        android:layout_marginLeft="30dp"
        android:layout_marginEnd="30dp"
        android:layout_marginRight="30dp"
        android:gravity="center"
        android:text="Upload Product Images"
        android:textColor="#f00fff"
        android:textSize="25sp" />

    <Button
        android:id="@+id/button_choose_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/text_view_show_uploads"
        android:layout_marginTop="50dp"
        android:text="Choose file" />
    <EditText
        android:id="@+id/edit_text_file_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_toEndOf="@+id/button_choose_image"
        android:layout_below="@id/text_view_show_uploads"
        android:layout_marginTop="50dp"
        android:hint="Enter file name"
        android:layout_marginLeft="16dp"
        android:layout_toRightOf="@+id/button_choose_image" />

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="371dp"
        android:layout_height="395dp"
        android:layout_above="@id/progress_bar"
        android:layout_below="@id/edit_text_file_name"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_marginTop="20dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp" />
    <ProgressBar
        android:id="@+id/progress_bar"
        style="@style/Widget.AppCompat.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/button_upload"
        android:layout_marginBottom="16dp" />
    <Button
        android:id="@+id/button_upload"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:text="Upload" />

</RelativeLayout>

没有错误,但上传的 URL 链接无法正常访问上传的图片。数据架构 data structure to save name and url

上传的图片 URL 看起来像 firebase 架构中给出的 ("com.google.android.gms.tasks.zzu@b72c6eb")。但完美的图片 URL 链接看起来像“https://firebasestorage.googleapis.com/v0/b/rewabazar-a2258.appspot.com/o/products%2F1619256818173.jpg?alt=media&token=a3f4acd3-e0fc-49d9-8548- 5e386bc2de84"

1 个答案:

答案 0 :(得分:1)

您的代码中有两个主要问题。第一个,您正在像这样定义以下 StorageReference 对象:

StorageReference fileReference = mStorageRef.child(System.currentTimeMillis() + "." + getFileExtension(mImageUri));

在那之后,你正在使用:

Task<Uri> url1 = fileReference.getDownloadUrl();

StorageReference 的“getDownloadUrl()”方法返回一个任务对象。只需在这样的对象上调用“toString()”,然后将其传递给 Upload 类构造函数:

Upload upload = new Upload(mEditTextFileName.getText().toString().trim(), url1.toString());

没有任何意义,因为该对象的字符串表示不是实际的 URL,它和内存中的地址,因此:

<块引用>

com.google.android.gms.tasks.zzu@b72c6eb

而且不是

<块引用>

https://firebasestorage.googleapis.com/v0/b/rewabazar-a2258.appspot.com/o/products%2F1619256818173.jpg?alt=media&token=a3f4acd3-e0fc-49d9-8548-5e386bc2de84

这是获取下载 URL 的推荐方式:

第二个问题是你在数据库中的字段名称与你班级中的字段名称不同。看到“mImageUrl”与“imageUrl”了吗?这是不正确的,两个名称必须匹配。您可以更改数据库中字段的名称以匹配类中的名称,或者在 getter 前使用注释:

@PropertyName("imageUrl")
public String getImageUrl() {
    return mImageUrl;
}

这是单个属性的示例,但您也应该对其他属性执行相同的操作。

相关问题