无法在 Firebase Firestore 中存储下载 URL

Posted

技术标签:

【中文标题】无法在 Firebase Firestore 中存储下载 URL【英文标题】:Not able to store download URLs inside Firebase Firestore 【发布时间】:2020-11-22 17:59:01 【问题描述】:

我正在尝试将图像存储到 Firebase 存储中,然后从 Firebase 存储中下载这些图像的 URI,然后使用 foreach 循环再次将这些 URI 上传到 firebase firestore。图像已成功上传到 Firebase 存储,但只有最后一张图像的 Uri 进入 Firestore,前三个失败。我创建了一个位图数组列表,然后在其上使用了 foreach 循环。

我的代码

    private void UploadingImage() 

        if (bitmap != null && bitmap2 != null && bitmap3 != null && bitmap4 != null) 

            StorageTask arrayUpload;
            fuser = FirebaseAuth.getInstance().getCurrentUser();
            ProductName = Objects.requireNonNull(Product_Name_EditText.getText()).toString();
            CityName = Objects.requireNonNull(CityNameEditText.getText()).toString();

            // Bitmap[] bitmaps=new Bitmap[3];
            ArrayList<Bitmap> bitmapArrayList = new ArrayList<>();
            bitmapArrayList.add(bitmap);
            bitmapArrayList.add(bitmap2);
            bitmapArrayList.add(bitmap3);
            bitmapArrayList.add(bitmap4);

            Bitmap bitresized;

            for (Bitmap bitUpload : bitmapArrayList)
            
                bitresized = Bitmap.createScaledBitmap(bitUpload, 800, 800, true);
                ByteArrayOutputStream baosArray = new ByteArrayOutputStream();
                bitresized.compress(Bitmap.CompressFormat.JPEG, 70, baosArray);
                byte[] uploadbaosarray = baosArray.toByteArray();
                i = i + 1;
                fileReference = storageReference.child(ProductName).child(i + ProductName + ".jpg");

                arrayUpload = fileReference.putBytes(uploadbaosarray);

                arrayUpload.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();
                         else if (task.isSuccessful()) 
                            Toast.makeText(Upload_New_Product.this, "Uploaded Successfully", Toast.LENGTH_SHORT).show();
                            //mProgressBar.setVisibility(View.INVISIBLE);
                        

                        return fileReference.getDownloadUrl();
                    
                ).addOnCompleteListener(new OnCompleteListener<Uri>() 
                    @Override
                    public void onComplete(@NonNull Task<Uri> task) 
                        if (task.isSuccessful()) 
                            Uri downloadUri = task.getResult();
                            assert downloadUri != null;
                            String mUri = downloadUri.toString();

                            ProductName = Product_Name_EditText.getText().toString();
                            ProductRef = db.collection("Sellers").document(CityName).collection(Uid).document(ProductName);
                            HashMap<String, Object> map = new HashMap<>();
                            map.put("imageURL" + i, mUri);
                            //reference.updateChildren(map);
                            ProductRef.set(map, SetOptions.merge());

                         else 
                            Toast.makeText(Upload_New_Product.this, "Failed!", Toast.LENGTH_SHORT).show();
                        
                    
                ).addOnFailureListener(new OnFailureListener() 
                    @Override
                    public void onFailure(@NonNull Exception e) 
                        Toast.makeText(Upload_New_Product.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                        //pd.dismiss();
                    
                );

            
        

【问题讨论】:

【参考方案1】:

由于上传(和获取下载 URL)是异步操作,for 循环几乎立即完成,之后所有上传都并行进行。这意味着当您的 map.put("imageURL" + i, mUri) 运行时,i 变量将成为它的最终值。

要使代码工作,您需要捕获循环中每次迭代的i 变量。一个简单的方法是将上传图像并将其 URL 存储到一个单独的函数中的代码,并将 i 的值传递给该函数调用。

类似:

public void uploadFileAtIndex(int i) 
    fileReference = storageReference.child(ProductName).child(i + ProductName + ".jpg");

    arrayUpload = fileReference.putBytes(uploadbaosarray);

    arrayUpload.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();
             else if (task.isSuccessful()) 
                Toast.makeText(Upload_New_Product.this, "Uploaded Successfully", Toast.LENGTH_SHORT).show();
            

            return fileReference.getDownloadUrl();
        
    ).addOnCompleteListener(new OnCompleteListener<Uri>() 
        @Override
        public void onComplete(@NonNull Task<Uri> task) 
            if (task.isSuccessful()) 
                Uri downloadUri = task.getResult();
                assert downloadUri != null;
                String mUri = downloadUri.toString();

                ProductName = Product_Name_EditText.getText().toString();
                ProductRef = db.collection("Sellers").document(CityName).collection(Uid).document(ProductName);
                HashMap<String, Object> map = new HashMap<>();
                map.put("imageURL" + i, mUri);
                ProductRef.set(map, SetOptions.merge());
             else 
                Toast.makeText(Upload_New_Product.this, "Failed!", Toast.LENGTH_SHORT).show();
            
        
    ).addOnFailureListener(new OnFailureListener() 
        @Override
        public void onFailure(@NonNull Exception e) 
            Toast.makeText(Upload_New_Product.this, e.getMessage(), Toast.LENGTH_SHORT).show();
        
    );

然后在循环中使用它:

for (Bitmap bitUpload : bitmapArrayList) 
    ...
    i = i + 1;
    uploadFileAtIndex(i);

您可能需要将更多的变量传递给uploadFileAtIndex,而不是我在此处所做的,但传递i 可以解决您现在遇到的问题。

【讨论】:

它没有解决问题我只是在你的代码中将参数从uploadFileAtIndex(int i) 更改为uploadFileAtIndex(int i, Bitmap bitmap)

以上是关于无法在 Firebase Firestore 中存储下载 URL的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 SwiftUI 从 Firebase / Firestore 中删除文档

Expo + firebase@9.0.1/9.0.0: @firebase/firestore:, Firestore (9.0.0): 无法到达 Cloud Firestore 后端

@firebase/firestore:Firestore (8.6.5):无法访问 Cloud Firestore 后端

@firebase/firestore:Firestore (8.6.2):无法访问 Cloud Firestore 后端(React Js)

无法在 Firebase Firestore 中存储下载 URL

@firebase/firestore:Firestore (5.0.4):无法访问 Cloud Firestore 后端。后端在 10 秒内没有响应