如何获取使用Android和Firebase上传的多张图片的下载URL

问题描述 投票:0回答:1

我在该网站上看到了类似的问题,但是大多数问题与获取单个上载图像的下载URL有关。从这些帖子中寻求帮助,现在我可以获得单个图像的下载URL。

但是当我尝试获取一起上传的多个图像的下载URL时,我遇到了一个问题。我想做三件事...

1。选择三张图片2.将它们上传到Firebase Cloud Storage3.获取上载图像的URL,并将其保存在ArrayList中。

我可以成功地完成前两件事,但是还没有实现第三件事。当我单击“更新”按钮时,所有图像均完美存储在Cloud Storage中,但在请求所有图像的下载URL时显示错误。

这里是单击“更新”按钮时的代码:

upload.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        progressDialog.setMessage("Uploading .... ");
        progressDialog.show();

        storageReference = FirebaseStorage.getInstance().getReference().child("Pictures");

        int uploadCount = 0;

        // imageList is an ArrayList<Uri> which holds the address of selected 3 images. 
        // imageAddress is an ArrayList<String> where I want to save all downloadUrls of images (each url is saved as a string).
        // imagePath is a StorageReference

        while(uploadCount < imageList.size()) {
            Log.d("UploadCount", uploadCount+"");
            Uri uri_Image = imageList.get(uploadCount); 
            imagePath = storageReference.child(uri_Image.getLastPathSegment());

            imagePath.putFile(uri_Image).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                    imagePath.getDownloadUrl().addOnSuccessListener(newOnSuccessListener<Uri>() {
                        @Override
                        public void onSuccess(Uri uri) {
                            Uri downloadUri = uri;
                            imageAddress.add(downloadUri.toString());
                            Log.d("ImageAddress Size: ", imageAddress.size()+"");
                        }
                    });
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Toast.makeText(SignOutActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
                    progressDialog.dismiss();
                }
            }); //.............
            if(uploadCount == (imageList.size()-1)) {
                Log.d("Good", "HELLO HELLO");
                Toast.makeText(SignOutActivity.this, "Successfully Uploaded", Toast.LENGTH_LONG).show();
                upload.setClickable(false);
                progressDialog.dismiss();
            }
            else {
                Log.d("BAD", "NOT HELLO "+uploadCount);
            }
            uploadCount = uploadCount + 1;

        }
    }
});

这里是错误:

2020-02-15 17:02:26.945 28207-28735/com.example.practiceapplication E/StorageException: StorageException has occurred.
    Object does not exist at location.
    Code: -13010 HttpResult: 404
2020-02-15 17:02:26.946 28207-28735/com.example.practiceapplication E/StorageException: {"error": {"code": 404, "message": "Not Found. Could not get object", "status": "GET_OBJECT"}}
    java.io.IOException: {"error": {"code": 404, "message": "Not Found. Could not get object", "status": "GET_OBJECT"}}
        at com.google.firebase.storage.network.NetworkRequest.parseResponse(com.google.firebase:firebase-storage@@19.1.1:433)
        at com.google.firebase.storage.network.NetworkRequest.parseErrorResponse(com.google.firebase:firebase-storage@@19.1.1:450)
        at com.google.firebase.storage.network.NetworkRequest.processResponseStream(com.google.firebase:firebase-storage@@19.1.1:441)
        at com.google.firebase.storage.network.NetworkRequest.performRequest(com.google.firebase:firebase-storage@@19.1.1:272)
        at com.google.firebase.storage.network.NetworkRequest.performRequest(com.google.firebase:firebase-storage@@19.1.1:286)
        at com.google.firebase.storage.internal.ExponentialBackoffSender.sendWithExponentialBackoff(com.google.firebase:firebase-storage@@19.1.1:70)
        at com.google.firebase.storage.internal.ExponentialBackoffSender.sendWithExponentialBackoff(com.google.firebase:firebase-storage@@19.1.1:62)
        at com.google.firebase.storage.GetDownloadUrlTask.run(com.google.firebase:firebase-storage@@19.1.1:76)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
        at java.lang.Thread.run(Thread.java:761)
2020-02-15 17:02:30.712 28207-28207/com.example.practiceapplication D/ImageAddress Size:: 1

如果有人告诉我更正,这将对我非常有帮助。谢谢

android image firebase firebase-storage
1个回答
0
投票

您的代码在处理异步代码和for循环时遇到了混合使用局部变量和共享全局变量的问题。

在上面的代码中,在for循环内使用全局变量imagePathimageAddressimageList,这最终是导致该异常的关键原因。

代码细分

单击upload按钮时,代码将执行以下步骤,并以粗体显示错误:

  • 获取第一张图片的URI
  • 更新imagePath的值以指向该图像的上载位置
  • 开始上传第一张图像
  • 日志"NOT HELLO 0"
  • 获取第二张图片的URI
  • 更新imagePath的值以指向该图像的上载位置
  • 开始上传第二张图像
  • 日志"NOT HELLO 1"
  • 获取第三张图片的URI
  • 更新imagePath的值以指向该图像的上载位置
  • 开始上载第三张图像
  • 日志"HELLO HELLO"和祝酒"Successfully Uploaded"(尚未实际完成)
  • [稍后]
  • 第一张图片完成上传
  • << [第三张图片的下载URL被请求((抛出StorageException]] >>第二张图像完成上传
  • 请求
  • 第三张图片
  • 的下载URL ((引发另一个StorageException] >>第三张图片完成上传
  • 请求第三张图片的下载URL(它将正常工作)
  • 修复
  • 要解决此问题,必须完成以下操作:

    使用imageList的局部变量副本
  • storageReference使用局部变量
  • 将局部变量用于imagePath,然后重命名为imageRef以准确反映其类型
  • imageAddress重命名为imageAddressList以准确反映其类型(推荐)
  • 删除while()循环并改为使用for迭代器
  • 立即而不是在最后一次禁用上传按钮
  • 上传每个图像并并行获取下载URL,而不会互相冲突
  • 仅在实际完成上传后才显示“成功上传”或“上传失败”消息
  • 仅更新一次imageAddressList,而不是异步更新。
  • 要做:
  • 点击currentUploadTask并将其绑定到视图对话框/通知以显示文件上传进度
  • 完成所有上传后更新用户界面
  • 更新的代码
  • 注意:这是徒手输入的-可能会有一些错别字。

upload.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { progressDialog.setMessage("Uploading .... "); progressDialog.show(); upload.setClickable(false); // disable upload button whilst uploading final StorageReference storageReference = FirebaseStorage.getInstance().getReference().child("Pictures"); final List<Uri> clonedImageList = new ArrayList<>(imageList); imageList.clear(); // empty old list? int imageListSize = clonedImageList.size(); List<Task<Uri>> uploadedImageUrlTasks = new ArrayList<>(imageListSize); for (Uri imageUri : clonedImageList) { final String imageFilename = imageUri.getLastPathSegment(); Log.d("upload.onClick()", "Starting upload for \"" + imageFilename + "\"..."); StorageReference imageRef = storageReference.child(imageFilename); // Warning: potential for collisions/overwrite UploadTask currentUploadTask = imageRef.putFile(imageUri); Task<Uri> currentUrlTask = currentUploadTask .continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() { @Override public Task<Uri> then(@NonNull Task<UploadTask.TaskSnapshot> task) throws Exception { if (!task.isSuccessful()) { Log.d("upload.onClick()", "Upload for \"" + imageFilename + "\" failed!"); throw task.getException(); // rethrow any errors } Log.d("upload.onClick()", "Upload for \"" + imageFilename + "\" finished. Fetching download URL..."); return imageRef.getDownloadUrl(); } }) .continueWithTask(new Continuation<Uri, Uri>() { // purely for logging to debug, recommended to remove @Override public Task<Uri> then(@NonNull Task<Uri> task) throws Exception { if (!task.isSuccessful()) { Log.d("upload.onClick()", "Could not get download URL for \"" + imageFilename + "\"!"); throw task.getException(); // rethrow any errors } Log.d("upload.onClick()", "Download URL for \"" + imageFilename + "\" is \"" + task.getResult() + "\"."); return task.getResult(); } }); uploadedImageUrlTasks.add(currentUrlTask); } // At this point, all the files are being uploaded in parallel // Each upload is tracked by the tasks in uploadedImageUrlTasks Tasks.whenAllComplete(uploadedImageUrlTasks) .addOnCompleteListener(new OnCompleteListener<List<Task<Uri>>>() { @Override public void onComplete(@NonNull List<Task<Uri>> tasks) { int tasksCount = tasks.size(); List<Uri> failedUploads = new ArrayList<>(); imageAddressList.clear(); // empty old entries? for (Task<Uri> task : tasks) { if (task.isSuccessful()) { successCount++; Uri downloadUri = task.getResult(); imageAddressList.add(downloadUri.toString()); } else { Uri imageUri = clonedImageList.get(tasks.indexOf(task)); failedUploads.add(imageUri); Log.e("upload.onClick()", "Failed to upload/fetch URL for \"" + imageUri.getLastPathSegment() + "\" with exception", task.getException()); // log exception } } progressDialog.dismiss(); // dismiss upload dialog if (failedUploads.size() > 0) { Toast.makeText(SignOutActivity.this, failedUploads.size() + "/" + tasksCount + " uploads failed.", Toast.LENGTH_LONG).show(); // TODO: Do something with list of failed uploads such as readd to the now empty upload list imageList.addAll(failedUploads); upload.setClickable(true); } else { Toast.makeText(SignOutActivity.this, "Successfully uploaded all " + tasksCount + " files.", Toast.LENGTH_LONG).show(); } // TODO: Now that imageAddressList has been updated, update the UI - e.g tell recycler view to refresh } }); } });

© www.soinside.com 2019 - 2024. All rights reserved.