Flutter中FirebaseStorage的Reference无exists方法报错求助
Flutter FirebaseStorage 报错:
The method 'exists' isn't defined for the type 'Reference' 问题说明
在Flutter项目中删除Firebase数据库关联的存储文件时,触发上述错误,问题出在检查文件是否存在的代码行:
bool exists = await FirebaseStorage.instance.ref(ref).exists();
核心原因是FirebaseStorage的Reference类并没有提供exists()方法,需要改用官方推荐的方式判断文件状态。
相关代码片段
构建文件引用路径的代码:
String ref = _selectedRef!; if (!ref.startsWith("/")) { ref = "/" + ref; } ref = ref.substring(0, ref.lastIndexOf("/") + 1) + ".pdf";
原判断逻辑代码:
if (exists) { await FirebaseStorage.instance.ref(ref).delete(); await FirebaseFirestore.instance .collection("file") .where("ref", isEqualTo: _selectedRef) .get() .then((snapshot) { snapshot.docs.first.reference.delete(); }); setState(() { _selectedRef = null; }); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("选中的文件不存在"))); }
解决方案
FirebaseStorage判断文件是否存在的正确方式是调用getMetadata()方法,通过捕获异常来判定:
- 文件存在时,
getMetadata()会正常返回元数据 - 文件不存在时,会抛出
FirebaseException异常(错误码为object-not-found)
修改deleteFirebaseData()方法中的检查逻辑:
// 替换原有的exists()调用 bool exists = true; try { await FirebaseStorage.instance.ref(ref).getMetadata(); } on FirebaseException catch (e) { if (e.code == 'object-not-found') { exists = false; } }
完整修正后的代码
import 'dart:io'; import 'dart:math'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:file_picker/file_picker.dart'; import 'package:fimprac/screen_acercade.dart'; import 'package:fimprac/screen_home.dart'; import 'package:fimprac/main.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/material.dart'; import 'package:flutter/src/material/navigation_drawer.dart'; import 'package:fimprac/menu.dart'; import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(MaterialApp( debugShowCheckedModeBanner: false, home: perfilSC(), )); } class perfilSC extends StatefulWidget { const perfilSC({super.key}); @override State<perfilSC> createState() => _perfilSCState(); } class _perfilSCState extends State<perfilSC> { String? _selectedRef; // 存储选中文件的引用 String url = ""; int? number; late QueryDocumentSnapshot selectedSnapshot; uploadDataToFirebase() async { // 生成随机数 number = Random().nextInt(10); // 选择PDF文件 FilePickerResult? result = await FilePicker.platform.pickFiles(); File pick = File(result!.files.single.path.toString()); var file = pick.readAsBytesSync(); String name = DateTime.now().millisecondsSinceEpoch.toString(); // 上传文件到Firebase Storage var pdfFile = FirebaseStorage.instance.ref().child(name).child("/.pdf"); UploadTask task = pdfFile.putData(file); TaskSnapshot snapshot = await task; url = await snapshot.ref.getDownloadURL(); String ref = name + "/.pdf"; // 设置文件引用路径 // 将文件信息上传到Firestore await FirebaseFirestore.instance.collection("file").doc().set({ 'fileUrl': url, 'num': "CV#" + number.toString(), 'ref': name + "/.pdf" // 存储文件引用路径 }); } Future<void> deleteFile() async { if (_selectedRef != null) { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text('确定要删除该文件吗?'), actions: <Widget>[ TextButton( child: const Text('取消'), onPressed: () { Navigator.of(context).pop(); }, ), TextButton( child: const Text('删除'), onPressed: () async { await deleteFirebaseData(); Navigator.of(context).pop(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("文件已删除"))); }, ), ], ); }, ); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("请先选择要删除的文件"))); } } Future<void> deleteFirebaseData() async { if (_selectedRef == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("请先选择要删除的文件"))); return; } // 构建完整的文件引用路径 String ref = _selectedRef!; if (!ref.startsWith("/")) { ref = "/" + ref; } ref = ref.substring(0, ref.lastIndexOf("/") + 1) + ".pdf"; // 判断文件是否存在 bool exists = true; try { await FirebaseStorage.instance.ref(ref).getMetadata(); } on FirebaseException catch (e) { if (e.code == 'object-not-found') { exists = false; } } if (exists) { await FirebaseStorage.instance.ref(ref).delete(); await FirebaseFirestore.instance .collection("file") .where("ref", isEqualTo: _selectedRef) .get() .then((snapshot) { snapshot.docs.first.reference.delete(); }); setState(() { _selectedRef = null; }); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("选中的文件不存在"))); } } @override Widget build(BuildContext context) { return Scaffold( drawer: const NavigationDrawerMenu(), appBar: AppBar( backgroundColor: Colors.green, title: const Text('PDF'), ), body: StreamBuilder( stream: FirebaseFirestore.instance.collection("file").snapshots(), builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) { if (snapshot.hasData) { return ListView.builder( itemCount: snapshot.data!.docs.length, itemBuilder: (context, i) { QueryDocumentSnapshot x = snapshot.data!.docs[i]; return InkWell( onTap: () { setState(() { selectedSnapshot = x; // 保存选中的文件快照 }); Navigator.push( context, MaterialPageRoute( builder: (context) => View( url: x['fileUrl'], ))); }, child: Container( margin: const EdgeInsets.symmetric(vertical: 10), child: Text(x["num"]), ), ); }); } return const Center( child: CircularProgressIndicator(), ); }), floatingActionButton: Row( children: [ FloatingActionButton( heroTag: "btn1", onPressed: () { setState(() { _selectedRef = selectedSnapshot['ref']; // 保存选中文件的引用 }); deleteFile(); }, child: const Icon(Icons.delete), ), const SizedBox(width: 10), Expanded( child: FloatingActionButton( heroTag: "btn2", onPressed: () => uploadDataToFirebase(), child: const Icon(Icons.add), ), ), ], ), ); } } class View extends StatelessWidget { PdfViewerController? _pdfViewerController; final url; View({this.url}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("PDF 预览"), ), body: SfPdfViewer.network( url, controller: _pdfViewerController, ), ); } }
内容的提问来源于stack exchange,提问作者GermanBMxD
相关产品推荐
相关产品推荐

