Firebase _upload 写入随机 downloadURL
Firebase _upload writes random downloadURL
下面是一个简单的 firebase 图片上传器。问题是它有时会使用另一个图像的 downloadURL 作为写入 Firestore 时的值。它可以毫无问题地将我的图像上传到云存储,但是当它将位置写入 firestore 时,它经常使用另一个图像的 URL。完整代码如下,但我省略了 UI。我如何确保它向 firestore 写入正确的 URL?
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:path/path.dart' as path;
import 'package:image_picker/image_picker.dart';
class ImagePicky2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// Remove the debug banner
debugShowCheckedModeBanner: false,
theme: ThemeData(primarySwatch: Colors.green),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
FirebaseStorage storage = FirebaseStorage.instance;
double? lat, lng;
File? file;
String? name, detail, pathImage, dateString;
// Select an image from the gallery or take a picture with the camera
// Then upload to Firebase Storage
Future<XFile?> _upload(String inputSource) async {
FirebaseAuth auth = FirebaseAuth.instance;
User firebaseUser = auth.currentUser!;
final picker = ImagePicker();
try {
final pickedImage = await picker.pickImage(
source: inputSource == 'camera'
? ImageSource.camera
: ImageSource.gallery,
imageQuality: 25,
maxWidth: 1920);
final String fileName = path.basename(pickedImage!.path);
File imageFile = File(pickedImage.path);
try {
// Uploading the selected image with some custom meta data
await storage.ref(fileName).putFile(
imageFile,
SettableMetadata(customMetadata: {
'uploaded_by': firebaseUser.displayName!,
'description': 'Some description...'
}));
// Refresh the UI
setState(() {});
} on FirebaseException catch (error) {
print(error);
}
} catch (err) {
print(err);
}
photoUploadFirestoreDetails();
}
// Retriew the uploaded images
// This function is called when the app launches for the first time or when an image is uploaded or deleted
Future<List<Map<String, dynamic>>> _loadImages() async {
FirebaseAuth auth = FirebaseAuth.instance;
User firebaseUser = auth.currentUser!;
List<Map<String, dynamic>> files = [];
final ListResult result = await storage.ref().list();
final List<Reference> allFiles = result.items;
await Future.forEach<Reference>(allFiles, (file) async {
final String fileUrl = await file.getDownloadURL();
pathImage = await file.getDownloadURL();
final FullMetadata fileMeta = await file.getMetadata();
files.add({
"url": fileUrl,
"path": file.fullPath,
"uploaded_by": fileMeta.customMetadata?['uploaded_by'] ?? firebaseUser.displayName,
"description":
fileMeta.customMetadata?['description'] ?? 'No description'
});
});
return files;
}
Future<Null> photoUploadFirestoreDetails() async {
Firebase.initializeApp();
Map<String, dynamic> map = Map();
map['PathImage'] = pathImage;
FirebaseFirestore firestore = FirebaseFirestore.instance;
CollectionReference collectionReference =
firestore.collection('MarkerCollect');
await collectionReference.doc().set(map).then((
value) {
});
}
}```
尝试使用此功能将图像上传到 fire-storage 并获取 Url
Future<String?> uploadAndGetUrl(File file) async {
try {
final Reference ref = FirebaseStorage.instance
.ref()
.child('profilePhoto')
.child(DateTime.now().microsecondsSinceEpoch.toString());
UploadTask uploadTask = ref.putFile(file);
await uploadTask.whenComplete(() {});
String url = await ref.getDownloadURL();
return url;
} catch (e) {
print('Firebase Storage Error is : $e');
return null;
}
}
或者您可以只上传图片,稍后 URL 获取图片。
你的上传图片功能看起来没问题。 名称应该是唯一的。否则,它 returns 不同的图像 url。
Future<String> getUrl(String imageName) async {
try {
Reference storageRef = FirebaseStorage.instance.ref().child('profilePhoto/$logo');
String url = await storageRef.getDownloadURL();
return url;
} catch (e) {
return null;
}
}
代码正在将随机下载 url 上传到 Firestore,因为您从 _loadImages
方法获取图像路径,该方法加载存储中的文件而不是使用下载 url 刚刚上传的文件。
这是有问题的代码:
Future<Null> photoUploadFirestoreDetails() async {
...
map['PathImage'] = pathImage;
...
}
解法:
您可以通过在上传后立即检索下载 url 并将其传递给要在 Firestore 上传中使用的 photoUploadFirestoreDetails
方法来解决此问题。
您还应该将 photoUploadFirestoreDetails
放在 try-catch
中。
检查下面的更新代码:
// _upload method
Future<XFile?> _upload(String inputSource) async {
FirebaseAuth auth = FirebaseAuth.instance;
User firebaseUser = auth.currentUser!;
final picker = ImagePicker();
try {
final pickedImage = await picker.pickImage(
source: inputSource == 'camera'
? ImageSource.camera
: ImageSource.gallery,
imageQuality: 25,
maxWidth: 1920);
final String fileName = path.basename(pickedImage!.path);
File imageFile = File(pickedImage.path);
try {
// Uploading the selected image with some custom meta data
final Reference storageReference = storage.ref(fileName);
await storageReference.putFile(
imageFile,
SettableMetadata(customMetadata: {
'uploaded_by': firebaseUser.displayName!,
'description': 'Some description...'
}));
final String downloadUrl = await storageReference.getDownloadURL();
// Refresh the UI
setState(() {});
await photoUploadFirestoreDetails(downloadUrl: downloadUrl);
} on FirebaseException catch (error) {
print(error);
}
} catch (err) {
print(err);
}
}
// photoUploadFirestoreDetails method
Future<Null> photoUploadFirestoreDetails({@required String downloadUrl}) async {
Firebase.initializeApp();
Map<String, dynamic> map = Map();
map['PathImage'] = downloadUrl;
FirebaseFirestore firestore = FirebaseFirestore.instance;
CollectionReference collectionReference =
firestore.collection('MarkerCollect');
var value = await collectionReference.doc().set(map);
}
下面是一个简单的 firebase 图片上传器。问题是它有时会使用另一个图像的 downloadURL 作为写入 Firestore 时的值。它可以毫无问题地将我的图像上传到云存储,但是当它将位置写入 firestore 时,它经常使用另一个图像的 URL。完整代码如下,但我省略了 UI。我如何确保它向 firestore 写入正确的 URL?
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:path/path.dart' as path;
import 'package:image_picker/image_picker.dart';
class ImagePicky2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// Remove the debug banner
debugShowCheckedModeBanner: false,
theme: ThemeData(primarySwatch: Colors.green),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
FirebaseStorage storage = FirebaseStorage.instance;
double? lat, lng;
File? file;
String? name, detail, pathImage, dateString;
// Select an image from the gallery or take a picture with the camera
// Then upload to Firebase Storage
Future<XFile?> _upload(String inputSource) async {
FirebaseAuth auth = FirebaseAuth.instance;
User firebaseUser = auth.currentUser!;
final picker = ImagePicker();
try {
final pickedImage = await picker.pickImage(
source: inputSource == 'camera'
? ImageSource.camera
: ImageSource.gallery,
imageQuality: 25,
maxWidth: 1920);
final String fileName = path.basename(pickedImage!.path);
File imageFile = File(pickedImage.path);
try {
// Uploading the selected image with some custom meta data
await storage.ref(fileName).putFile(
imageFile,
SettableMetadata(customMetadata: {
'uploaded_by': firebaseUser.displayName!,
'description': 'Some description...'
}));
// Refresh the UI
setState(() {});
} on FirebaseException catch (error) {
print(error);
}
} catch (err) {
print(err);
}
photoUploadFirestoreDetails();
}
// Retriew the uploaded images
// This function is called when the app launches for the first time or when an image is uploaded or deleted
Future<List<Map<String, dynamic>>> _loadImages() async {
FirebaseAuth auth = FirebaseAuth.instance;
User firebaseUser = auth.currentUser!;
List<Map<String, dynamic>> files = [];
final ListResult result = await storage.ref().list();
final List<Reference> allFiles = result.items;
await Future.forEach<Reference>(allFiles, (file) async {
final String fileUrl = await file.getDownloadURL();
pathImage = await file.getDownloadURL();
final FullMetadata fileMeta = await file.getMetadata();
files.add({
"url": fileUrl,
"path": file.fullPath,
"uploaded_by": fileMeta.customMetadata?['uploaded_by'] ?? firebaseUser.displayName,
"description":
fileMeta.customMetadata?['description'] ?? 'No description'
});
});
return files;
}
Future<Null> photoUploadFirestoreDetails() async {
Firebase.initializeApp();
Map<String, dynamic> map = Map();
map['PathImage'] = pathImage;
FirebaseFirestore firestore = FirebaseFirestore.instance;
CollectionReference collectionReference =
firestore.collection('MarkerCollect');
await collectionReference.doc().set(map).then((
value) {
});
}
}```
尝试使用此功能将图像上传到 fire-storage 并获取 Url
Future<String?> uploadAndGetUrl(File file) async {
try {
final Reference ref = FirebaseStorage.instance
.ref()
.child('profilePhoto')
.child(DateTime.now().microsecondsSinceEpoch.toString());
UploadTask uploadTask = ref.putFile(file);
await uploadTask.whenComplete(() {});
String url = await ref.getDownloadURL();
return url;
} catch (e) {
print('Firebase Storage Error is : $e');
return null;
}
}
或者您可以只上传图片,稍后 URL 获取图片。
你的上传图片功能看起来没问题。 名称应该是唯一的。否则,它 returns 不同的图像 url。
Future<String> getUrl(String imageName) async {
try {
Reference storageRef = FirebaseStorage.instance.ref().child('profilePhoto/$logo');
String url = await storageRef.getDownloadURL();
return url;
} catch (e) {
return null;
}
}
代码正在将随机下载 url 上传到 Firestore,因为您从 _loadImages
方法获取图像路径,该方法加载存储中的文件而不是使用下载 url 刚刚上传的文件。
这是有问题的代码:
Future<Null> photoUploadFirestoreDetails() async {
...
map['PathImage'] = pathImage;
...
}
解法:
您可以通过在上传后立即检索下载 url 并将其传递给要在 Firestore 上传中使用的 photoUploadFirestoreDetails
方法来解决此问题。
您还应该将 photoUploadFirestoreDetails
放在 try-catch
中。
检查下面的更新代码:
// _upload method
Future<XFile?> _upload(String inputSource) async {
FirebaseAuth auth = FirebaseAuth.instance;
User firebaseUser = auth.currentUser!;
final picker = ImagePicker();
try {
final pickedImage = await picker.pickImage(
source: inputSource == 'camera'
? ImageSource.camera
: ImageSource.gallery,
imageQuality: 25,
maxWidth: 1920);
final String fileName = path.basename(pickedImage!.path);
File imageFile = File(pickedImage.path);
try {
// Uploading the selected image with some custom meta data
final Reference storageReference = storage.ref(fileName);
await storageReference.putFile(
imageFile,
SettableMetadata(customMetadata: {
'uploaded_by': firebaseUser.displayName!,
'description': 'Some description...'
}));
final String downloadUrl = await storageReference.getDownloadURL();
// Refresh the UI
setState(() {});
await photoUploadFirestoreDetails(downloadUrl: downloadUrl);
} on FirebaseException catch (error) {
print(error);
}
} catch (err) {
print(err);
}
}
// photoUploadFirestoreDetails method
Future<Null> photoUploadFirestoreDetails({@required String downloadUrl}) async {
Firebase.initializeApp();
Map<String, dynamic> map = Map();
map['PathImage'] = downloadUrl;
FirebaseFirestore firestore = FirebaseFirestore.instance;
CollectionReference collectionReference =
firestore.collection('MarkerCollect');
var value = await collectionReference.doc().set(map);
}