关于dart:如何使用flutter删除Firebase Storage文件?

How to delete a Firebase Storage file with flutter?

我是Flutter和Firebase的新手,所以请耐心等待。

我正在尝试使用文件Url删除Firebase存储中的文件。

我拥有文件的完整网址,并删除文件路径以外的所有字符。

然后我尝试删除该文件。从下面的其他答案开始,我使用命令;
FirebaseStorage.instance.ref().child(filePath).delete()

下面是我的代码;

1
2
3
4
5
6
7
8
9
static void deleteFireBaseStorageItem(String fileUrl){

  String filePath = 'https://firebasestorage.googleapis.com/v0/b/dial-i-2345.appspot.com/o/default_images%2Fuser.png?alt=media&token=c2ccceec-8d24-42fe-b5c0-c987733ac8ae'
                  .replaceAll(new
                  RegExp(r'https://firebasestorage.googleapis.com/v0/b/dial-in-2345.appspot.com/o/'), '');

  FirebaseStorage.instance.ref().child(filePath).delete().then((_) => print('Successfully deleted $filePath storage item' ));

}

问题是文件永远不会被删除。

我想我已经找到问题所在了。

.delete()方法中,必须有一个'app'和'storageBucket'值。

当我运行此函数时,其值为null。

See screen shot

我觉得这很混乱,因为在同一个文件中我看到了这个;

1
2
3
4
5
6
7
8
9
/// The [FirebaseApp] instance to which this [FirebaseStorage] belongs.
///
/// If null, the default [FirebaseApp] is used.
final FirebaseApp app;

/// The Google Cloud Storage bucket to which this [FirebaseStorage] belongs.
///
/// If null, the storage bucket of the specified [FirebaseApp] is used.
final String storageBucket;enter code here

从文档中我可以看到,也许我需要使用" Firebase core"插件来制作将存储桶链接到该数据库的应用。但是Dart并没有什么特别的


更新(2019-08-03):

根据此PR,FlutterFire中现在有一个getReferenceFromUrl方法,该方法允许通过下载URL查找存储引用。

上一个答案:

在Android上,您可以调用getReferenceForUrl()从下载URL获取StorageReference,iOS上也存在类似的方法。

但是我在FlutterFire参考文档中找不到相应的方法。不幸的是,这意味着在Flutter中无法从下载URL映射回StorageReference

这听起来像是一个遗漏,因此我建议您在此功能请求中强制使用您的1。

目前,这意味着您需要在Cloud Storage中具有文件的相对路径,才能将其从Flutter中删除。使用该路径,您当前的代码将起作用。


将filePath更改为

1
2
3
4
5
String filePath = 'https://firebasestorage.googleapis.com/v0/b/dial-in-21c50.appspot.com/o/default_images%2Fuser.png?alt=media&token=c2ccceec-8d24-42fe-b5c0-c987733ac8ae'
                  .replaceAll(new
                  RegExp(r'https://firebasestorage.googleapis.com/v0/b/dial-in-21c50.appspot.com/o/default_images%2F'), '').split('?')[0];

FirebaseStorage.instance.ref().child(filePath).delete().then((_) => print('Successfully deleted $filePath storage item' ));

对于@Frank van Puffelen,这里的答案是参考URL从中删除Firebase存储中文件的代码片段。

1
2
3
4
5
6
7
8
9
10
11
  if (oldUrl != null) {
  var fileUrl = Uri.decodeFull(Path.basename(oldUrl))
      .replaceAll(new RegExp(r'(\\?alt).*'), '');
  StorageReference photoRef = await FirebaseStorage.instance
      .ref()
      .getStorage()
      .getReferenceFromUrl(oldUrl);
  try {
    await photoRef.delete();
  } catch (e) {}
}

完整方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Future<UserItem> uploadUserImage(String filePath, {String oldUrl}) async {
 if (oldUrl != null) {
  var fileUrl = Uri.decodeFull(Path.basename(oldUrl))
      .replaceAll(new RegExp(r'(\\?alt).*'), '');
  StorageReference photoRef = await FirebaseStorage.instance
      .ref()
      .getStorage()
      .getReferenceFromUrl(oldUrl);
  try {
    await photoRef.delete();
  } catch (e) {}
}

Im.Image image = Im.decodeImage(File(filePath).readAsBytesSync());

// todo cleanup string formation
final StorageReference storageReference =
    FirebaseStorage().ref().child('user_images').child(
          DateTime.now().millisecondsSinceEpoch.toString() +
              '.' +
              filePath.split(".")[1],
        );
final StorageUploadTask uploadTask = storageReference.putFile(
  File(filePath),
);

/// wait for upload to complete
await uploadTask.onComplete;

/// get the uploaded items url
String url = await (storageReference.getDownloadURL());

/// add the pic to FireStore Instance
FirebaseUser user = await FirebaseAuth.instance.currentUser();
String token = user.uid;

/// adds the item to the corresponding token path
await _fireStore
    .document('$token')
    .setData({'userImage': url}, merge: true);

return await getUserData();
}

我实现了一个更简洁的代码,但与使用Uri.decodeFull()Path.basename()的@earyhe相同。尝试并且成功。

1
2
3
4
5
6
7
8
9
10
11
import 'package:path/path.dart' as Path;


  Future<void> deleteImage(String imageFileUrl) async {
  var fileUrl = Uri.decodeFull(Path.basename(imageFileUrl)).replaceAll(new RegExp(r'(\\?alt).*'), '');


final StorageReference firebaseStorageRef =
    FirebaseStorage.instance.ref().child(fileUrl);
    await firebaseStorageRef.delete();
 }

1
2
3
4
5
6
 if (post.imageURL != null) {
    StorageReference photoRef =
        await FirebaseStorage.instance.getReferenceFromUrl(post.imageURL);

    await photoRef.delete();
  }


随着最新的重大更改,这是我使用的以下简单方法。

  • 将最新的firebase_storage以及它需要的所有其他相关更新导入到pubspec.yaml。当前,这是firebase_storage的以下内容:

    依赖项:
    firebase_storage:^ 7.0.0

  • 按如下所示导入软件包:

    将'package:firebase_storage / firebase_storage.dart'导入为firebase_storage;

  • 最后,在try catch中,您可以执行以下操作:

    尝试
    {
    等待firebase_storage.FirebaseStorage.instance.ref('/ images / something.jpg')。delete();
    }抓住(e){
    debugPrint('错误删除$ yourReference:$ e');
    }


  • === 2020年12月===

    非常感谢您的回答,这只是一个更新,因为旧方法导致我的应用崩溃。

    1
    2
    3
    4
    5
    6
    import 'package:firebase_storage/firebase_storage.dart';
    import 'package:path/path.dart' as Path;

    String fileUrl =Uri.decodeFull(Path.basename(i)).replaceAll(RegExp(r'(\\?alt).*'), '');
    StorageReference ref = FirebaseStorage.instance.ref().child(fileUrl);
    await ref.delete();

    您必须创建StorageReference storageReference;的实例,然后像

    一样对其进行初始化

    1
    2
    storageReference = await FirebaseStorage.instance
                                  .getReferenceFromUrl('photoUrl');

    您必须具有photoUrl,以便storageReference指向正确的图像。然后像

    一样删除它

    1
    storageReference.delete();

    全部完成。


    此功能对于Firebase存储链接非常有效

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    static Future<bool> deleteFileFromFirebaseByUrl(String urlFile) async {
    String fileName = urlFile.replaceAll("/o/","*");
    fileName = fileName.replaceAll("?","*");
    fileName = fileName.split("*")[1];
    print(fileName);
    StorageReference storageReferance = FirebaseStorage.instance.ref();
    storageReferance
        .child(fileName)
        .delete()
        .then((_) => print('Successfully deleted $fileName storage item')); }