flutterで画像をCloud firestoreにアップロードした際に、無効なURLで保存されてしまいます。
[firebase_storage/object-not-found] no object exists at the desired reference flutter
以上のようなエラーが発生しています。
ここでListTitleに入れている3行目のbook.imageURLを2個目のコードで代入しています。
final ListTiles = books .map((book) => ListTile( leading: Image.network(book.imageURL), title: Text(book.title), trailing: IconButton( icon: Icon(Icons.edit), onPressed: () async { // todo: 画面遷移 await Navigator.push( context, MaterialPageRoute( builder: (context) => AddBookPage( book: book, ), //画面の下からでてくる fullscreenDialog: true, ), ); model.fetchBooks(); }, ), onLongPress: () async { //todo: 削除 await showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: Text('${book.title}を削除しますか?'), actions: <Widget>[ TextButton( child: Text('OK'), onPressed: () async { Navigator.of(context).pop(); // TODO:削除のAPIを叩く await daleteBook(context, model, book); }, ), ], ); }, ); }, ))
以下にimageURLを代入するために実装したコードを載せます。
dart
1import 'dart:io'; 2 3import 'package:cloud_firestore/cloud_firestore.dart'; 4import 'package:coriander/domain/book.dart'; 5import 'package:firebase_storage/firebase_storage.dart'; 6import 'package:flutter/material.dart'; 7 8class AddBookModel extends ChangeNotifier { 9 String bookTitle = ''; 10 File imageFile; 11 bool isLoading = false; 12 13 startLoading() { 14 isLoading = true; 15 notifyListeners(); 16 } 17 18 endLoading() { 19 isLoading = false; 20 notifyListeners(); 21 } 22 23 Future addBookToFirebase() async { 24 if (bookTitle.isEmpty) { 25 throw ('タイトルを入力してください'); 26 } 27 final imageURL = await _uploadImageFile(); 28 29 FirebaseFirestore.instance.collection('books').add( 30 { 31 'title': bookTitle, 32 'imageURL': imageURL, 33 'createdAt': Timestamp.now(), 34 }, 35 ); 36 } 37 38 setImage(File imageFile) { 39 this.imageFile = imageFile; 40 notifyListeners(); 41 } 42 43 Future<String> _uploadImageFile() async { 44 if (imageFile == null) { 45 return ''; 46 } 47 final storage = FirebaseStorage.instance; 48 final ref = storage.ref().child('books').child(bookTitle); 49 50 final snapshot = await ref 51 .putFile( 52 imageFile, 53 ) 54 .snapshot; 55 56 final downloadURL = await snapshot.ref.getDownloadURL(); 57 print(downloadURL); 58 return downloadURL; 59 } 60 61 Future updateBook(Book book) async { 62 final imageURL = await _uploadImageFile(); 63 final document = 64 FirebaseFirestore.instance.collection('books').doc(book.documentID); 65 await document.update( 66 { 67 'title': bookTitle, 68 'imageURL': imageURL, 69 'updateAt': Timestamp.now(), 70 }, 71 ); 72 } 73} 74
dart
1import 'dart:io'; 2 3import 'package:coriander/domain/book.dart'; 4import 'package:flutter/material.dart'; 5import 'package:image_picker/image_picker.dart'; 6import 'package:provider/provider.dart'; 7 8import 'add_book_model.dart'; 9 10class AddBookPage extends StatelessWidget { 11 AddBookPage({this.book}); 12 final Book book; 13 14 final picker = ImagePicker(); 15 16 17 Widget build(BuildContext context) { 18 final bool isUpdate = book != null; 19 final textEditingController = TextEditingController(); 20 21 if (isUpdate) { 22 textEditingController.text = book.title; 23 } 24 25 return ChangeNotifierProvider<AddBookModel>( 26 create: (_) => AddBookModel(), 27 child: Stack( 28 children: <Widget>[ 29 Scaffold( 30 appBar: AppBar( 31 title: Text(isUpdate ? '本を編集' : '本を追加'), 32 ), 33 body: Consumer<AddBookModel>( 34 builder: (context, model, child) { 35 return Padding( 36 padding: const EdgeInsets.all(8.0), 37 child: Column( 38 children: <Widget>[ 39 InkWell( 40 onTap: () async { 41 // TODO: カメラロール開いて写真選ぶ 42 final pickedFile = await picker.getImage( 43 source: ImageSource.gallery); 44 model.setImage(File(pickedFile.path)); 45 }, 46 child: SizedBox( 47 width: 100, 48 height: 160, 49 child: model.imageFile != null 50 ? Image.file(model.imageFile) 51 : Container( 52 color: Colors.grey, 53 ), 54 ), 55 ), 56 TextField( 57 controller: textEditingController, 58 onChanged: (text) { 59 model.bookTitle = text; 60 }, 61 ), 62 ElevatedButton( 63 child: Text(isUpdate ? '更新する' : '追加する'), 64 onPressed: () async { 65 model.startLoading(); 66 67 if (isUpdate) { 68 await updateBook(model, context); 69 } else { 70 // firestoreに本を追加 71 await addBook(model, context); 72 } 73 model.endLoading(); 74 }, 75 ), 76 ], 77 ), 78 ); 79 }, 80 ), 81 ), 82 Consumer<AddBookModel>(builder: (context, model, child) { 83 return model.isLoading 84 ? Container( 85 color: Colors.black.withOpacity(0.3), 86 child: Center( 87 child: CircularProgressIndicator(), 88 ), 89 ) 90 : SizedBox(); 91 }), 92 ], 93 ), 94 ); 95 } 96 97 Future addBook(AddBookModel model, BuildContext context) async { 98 try { 99 await model.addBookToFirebase(); 100 await showDialog( 101 context: context, 102 builder: (BuildContext context) { 103 return AlertDialog( 104 title: Text('保存しました!'), 105 actions: <Widget>[ 106 TextButton( 107 child: Text('OK'), 108 onPressed: () { 109 Navigator.of(context).pop(); 110 }, 111 ), 112 ], 113 ); 114 }, 115 ); 116 Navigator.of(context).pop(); 117 } catch (e) { 118 showDialog( 119 context: context, 120 builder: (BuildContext context) { 121 return AlertDialog( 122 title: Text(e.toString()), 123 actions: <Widget>[ 124 ElevatedButton( 125 child: Text('OK'), 126 onPressed: () { 127 Navigator.of(context).pop(); 128 }, 129 ), 130 ], 131 ); 132 }, 133 ); 134 } 135 } 136 137 Future updateBook(AddBookModel model, BuildContext context) async { 138 try { 139 await model.updateBook(book); 140 await showDialog( 141 context: context, 142 builder: (BuildContext context) { 143 return AlertDialog( 144 title: Text('更新しました!'), 145 actions: <Widget>[ 146 TextButton( 147 child: Text('OK'), 148 onPressed: () { 149 Navigator.of(context).pop(); 150 }, 151 ), 152 ], 153 ); 154 }, 155 ); 156 Navigator.of(context).pop(); 157 } catch (e) { 158 showDialog( 159 context: context, 160 builder: (BuildContext context) { 161 return AlertDialog( 162 title: Text(e.toString()), 163 actions: <Widget>[ 164 TextButton( 165 child: Text('OK'), 166 onPressed: () { 167 Navigator.of(context).pop(); 168 }, 169 ), 170 ], 171 ); 172 }, 173 ); 174 } 175 } 176} 177
回答1件
あなたの回答
tips
プレビュー