Firebase图片上传异常:存在的图片提示不存在及多图更新失败
问题分析与解决方案
问题1:错误提示「image file does not exist at uri」但图片实际存在
你的fileExists方法存在逻辑缺陷:当Uri是content://协议(比如从系统相册、媒体库选择的图片)时,uri.getPath()返回的并非真实本地文件路径,而是媒体数据库的内部标识,直接用File(uri.getPath())判断存在性必然返回false,导致错误提示。
修复方案
替换fileExists方法,通过ContentResolver检查Uri对应的资源是否可访问:
private boolean fileExists(Uri uri) { if (uri == null) return false; try { // 尝试打开输入流,能打开则说明资源存在且可访问 InputStream inputStream = getContentResolver().openInputStream(uri); if (inputStream != null) { inputStream.close(); return true; } } catch (IOException e) { Log.e(TAG, "Failed to check file existence: " + e.getMessage()); } return false; }
问题2:上传第二张及更多图片时无法更新到Firebase
当前代码的上传逻辑存在两个核心问题:
- save方法触发条件过于严格:只有当所有图片上传成功(
uploadCount.incrementAndGet() == imageUris.size())时才会调用save,但只要有一张上传失败,这个条件就无法满足,导致所有成功上传的图片URL都无法更新到数据库。 - CountDownLatch与uploadCount的逻辑冲突:每个上传任务不管成功失败都会调用
latch.countDown(),但save仅在全部成功时执行,导致latch等待完成后,可能没有触发数据库更新。
修复方案
调整上传逻辑,收集所有成功上传的图片URL,在所有上传任务完成后统一调用save方法更新数据库:
if (!imageUris.isEmpty()) { List<String> imageUrls = new ArrayList<>(); CountDownLatch latch = new CountDownLatch(imageUris.size()); for (int i = 0; i < imageUris.size(); i++) { Uri imageUri = imageUris.get(i); if (imageUri == null) { Log.e(TAG, "ImageUri is null."); latch.countDown(); continue; } if (!fileExists(imageUri)) { Log.e(TAG, "Image file does not exist at Uri: " + imageUri.toString()); latch.countDown(); continue; } StorageReference imageRef = storageReference.child("hotel_images/" + hotelId + "/image" + (i + 1)); UploadTask uploadTask = imageRef.putFile(imageUri); uploadTask.addOnSuccessListener(taskSnapshot -> { imageRef.getDownloadUrl().addOnSuccessListener(downloadUri -> { imageUrls.add(downloadUri.toString()); latch.countDown(); }).addOnFailureListener(e -> { Log.e("image upload", "Failed to get download URL: " + e.getMessage()); latch.countDown(); }); }).addOnFailureListener(e -> { Log.e("image upload", "Upload failed: " + e.getMessage()); latch.countDown(); }); } new Thread(() -> { try { latch.await(); // 所有上传任务完成后,统一更新数据库 save(hotelId, imageUrls, hotelName, hotelAddress, hotelDescription, hotelContact, hotelEmail, roomTypes, cancellationPolicy, amenitiesHotel, gcashNumber, gcashName, reservationFee, latitude, longitude); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } else { // 无图片时直接更新数据库 save(hotelId, null, hotelName, hotelAddress, hotelDescription, hotelContact, hotelEmail, roomTypes, cancellationPolicy, amenitiesHotel, gcashNumber, gcashName, reservationFee, latitude, longitude); }
额外注意点
- 原代码中
update方法的参数hotelId被onDataChange里的childSnapshot.getKey()覆盖,如果你的业务逻辑是要更新指定的hotelId,需要调整Query逻辑,避免遍历所有用户的酒店(当前Query是orderByChild("user_id").equalTo(userId),会返回该用户下的所有酒店)。 - 建议在save方法中处理
imageUrls为空的情况(比如所有图片上传失败时,是否保留原图片URL或清空)。
内容的提问来源于stack exchange,提问作者Kitlolz012
相关产品推荐
相关产品推荐

