2

I'm trying to upload and download images from Firabase Database which has an URL link to Firebase Storage. The problem is that the strange URL is being saved to database (see the link at the bottom). What should I do to obtain a normal URL that I will be able to use do downloand the image into my Android app? Thank you in advance!

Here I post some code I use:

Upload to Firebase DataBase and Storage:

mStorageRef = FirebaseStorage.getInstance().getReference();
mDataBaseRef = FirebaseDatabase.getInstance().getReference();

if (mImageUri != null)
{
    final StorageReference fileReference = mStorageRef.child(nameimage + "." + getFileExtension(mImageUri));

    fileReference.putFile(mImageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
        @Override
        public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {

            Toast.makeText(AddAdvertisement.this, "Upload successful!", Toast.LENGTH_LONG).show();

            Upload upload = new Upload(et_localization, taskSnapshot.getUploadSessionUri().toString());
            String uploadId = mDataBaseRef.push().getKey();
            mDataBaseRef.child(uploadId).setValue(upload);


        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            Toast.makeText(AddAdvertisement.this, e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    });

And download from Firebase:

databaseReference = FirebaseDatabase.getInstance().getReference();

databaseReference.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

        for (DataSnapshot postSnapshot : dataSnapshot.getChildren())
        {
            Upload upload = postSnapshot.getValue(Upload.class);
            mUploads.add(upload);
        }

        mAdapter = new AdverisementAdapter(getContext(),mUploads);
        mrecyclerView.setAdapter(mAdapter);
    }

and Picasso to retreive image:

@Override
public void onBindViewHolder(@NonNull ImageViewHolder imageViewHolder, int i) {

    Upload uploadCurrent = mUploads.get(i);

    imageViewHolder.textViewName.setText(uploadCurrent.getName());

    Picasso.get().load(uploadCurrent.getUrl()).into(imageViewHolder.imageView);
}

Picasso work fine, beacuse except form an image I also get from Firebase string with the name, which is downloaded appropriately. So, the problem I think it's just with this wrong url:

https://firebasestorage.googleapis.com/v0/b/my_name/o?name=image.jpg&uploadType=resumable&upload_id=AEnB2UrrOhqOVqTHuRRVRmlkf4Gh6y5xd_w5IvRok1SNVOMNnz34dqWFJ5_lPD0DNJr05mrHrT8g97sy0d4BZAdiB6v7skkLSQ&upload_protocol=resumable

When I try to entered this link, I receive this kind of error:

Invalid request. X-Goog-Upload-Command header is missing.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

4 Answers4

5

You're writing this value to the database:

taskSnapshot.getUploadSessionUri().toString()

This is the URI of the upload session, which you can use to resume an upload in case it gets aborted.

Since you want to store the download URL, this call is pretty useless for your cause. Instead you should call getDownloadUrl() to (asynchronously) get the download URL for the newly uploaded file:

fileReference.putFile(mImageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {

        Toast.makeText(AddAdvertisement.this, "Upload successful!", Toast.LENGTH_LONG).show();

        fileReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
            @Override
            public void onSuccess(Uri uri) {
                String url = uri.toString();
                Upload upload = new Upload(et_localization, url);
                String uploadId = mDataBaseRef.push().getKey();
                mDataBaseRef.child(uploadId).setValue(upload);
            }
        });

    }
})...

Note that this is quite well described in the Firebase documentation on getting a download URL after uploading a file, which event includes a sample of accomplishing the same by using continueWithTask instead of nesting callbacks (which I did above).

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • getting error getDownloadUrl() is not supported at the root of the bucket. – Muhammed Haris Mar 01 '20 at 13:54
  • 1
    That means you're calling `getDownloadUrl()` on a `Reference` to the root of the bucket. You need to call it on a reference to a specific file in that bucket. Also see https://stackoverflow.com/questions/56933277/unable-to-retrieve-images-download-url-from-firebase-storage-getting-exception – Frank van Puffelen Mar 01 '20 at 16:02
2

According to the official documentation regarding UploadTask.TaskSnapshot's getUploadSessionUri() method:

Returns the session Uri, valid for approximately one week, which can be used to resume an upload later by passing this value into putFile(Uri, StorageMetadata, Uri).

I'm afraid that this is not the Uri that you are looking for. To get the correct uri, please see my answer from this post.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
2
fileReference.putFile(mImageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
    @Override
    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {

        Toast.makeText(AddAdvertisement.this, "Upload successful!", Toast.LENGTH_LONG).show();

        fileReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
            @Override
            public void onSuccess(Uri uri) {
                
               // just do your task //like hashmaps to put in

            }
        });

    }
})
1

That did not worked for me (using Expo), but using XMLHttpRequest did. I've found this solution here: https://github.com/expo/expo/issues/2402#issuecomment-443726662

My code is below, in case it can help.

_uploadImageAsync = async (uri) => {
  try {
    const blob = await new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest();
      xhr.onload = function () {
        resolve(xhr.response);
      };
      xhr.onerror = function (e) {
        console.log(e);
        reject(new TypeError('Network request failed'));
      };
      xhr.responseType = 'blob';
      xhr.open('GET', uri, true);
      xhr.send(null);
    });

    const ref = firebase
      .storage()
      .ref()
      .child('images/usersPicture/test');
    const snapshot = await ref.put(blob);

    blob.close();

    return await snapshot.ref.getDownloadURL();
  } catch(error) {
    console.log(error)
  }
}