在颤动中将图像从图像选择器保存到firebase存储
Posted
技术标签:
【中文标题】在颤动中将图像从图像选择器保存到firebase存储【英文标题】:Save Image from Image picker to firebase Storage in flutter 【发布时间】:2020-12-13 16:44:14 【问题描述】:我正在尝试在 firebase 存储中上传图像,通过访问相机从图像选择器插件中获取图像。图片未上传。我还补充说我更改了 Firebase 规则,因此只有经过身份验证的用户才能上传图像。 Git 中心Repo。我使用了 auth_screen.dart 第 48 到 59 行[我暂时注释掉] 处定义的图片上传逻辑。当我添加这些行时,我还添加了我之前运行良好的其他 firebase 功能。得到错误。
auth_screen.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
// import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/services.dart';
import '../widgets/auth/auth_form.dart';
class AuthScreen extends StatefulWidget
@override
_AuthScreenState createState() => _AuthScreenState();
class _AuthScreenState extends State<AuthScreen>
final _auth = FirebaseAuth.instance;
var _isLoading = false;
void _submitAuthForm(
String email,
String password,
String userName,
File userImage,
bool isLogin,
BuildContext ctx,
) async
dynamic authResult;
try
setState(()
_isLoading = true;
);
if (isLogin)
authResult = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
else
print(email);
print(userName);
print(userImage.path);
authResult = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
// final FirebaseStorage storage = FirebaseStorage(
// app: FirebaseStorage.instance.app,
// storageBucket: 'gs://chatapp-1b780.appspot.com',
// );
// final StorageReference ref2 =
// storage.ref().child('userimage').child('$authResult.user.id.jpg');
// final StorageUploadTask uploadTask = ref2.putFile(userImage);
// uploadTask.onComplete
// .then((value) => print(value))
// .catchError((error) => print(error));
// print(uploadTask.lastSnapshot.error.toString());
// ///...
// final ref = FirebaseStorage.instance
// .ref()
// .child('user_image')
// .child(authResult.user.id + '.jpg');
// await ref.putFile(userImage).onComplete;
///
await FirebaseFirestore.instance
.collection('users')
.doc(authResult.user.uid)
.set(
'username': userName,
'email': email,
);
on PlatformException catch (error)
var message = 'An error occured,Please check your credentials';
if (error.message != null)
setState(()
_isLoading = false;
);
message = error.message;
print(message);
catch (error)
setState(()
_isLoading = false;
);
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text(error.toString()),
backgroundColor: Theme.of(ctx).errorColor,
),
);
@override
Widget build(BuildContext context)
return Scaffold(
backgroundColor: Theme.of(context).primaryColor,
body: AuthForm(_submitAuthForm, _isLoading),
);
使用图像选择器从 auth/auth_form.dart 到 user_image_picker.dart 选择图像,我在其中添加了参数,以便将图像传递下来。 auth/authform.dart
import 'package:flutter/material.dart';
import 'dart:io';
import '../pickers/user_image_picker.dart';
class AuthForm extends StatefulWidget
final bool isLoading;
final void Function(String email, String password, String userName,
File userImage, bool isLogin, BuildContext ctx) submitFn;
AuthForm(this.submitFn, this.isLoading);
@override
_AuthFormState createState() => _AuthFormState();
class _AuthFormState extends State<AuthForm>
final _formKey = GlobalKey<FormState>();
var _isLogin = true;
String _userEmail = '';
String _userName = '';
String _userPassword = '';
File _userImageFile;
void _pickedImage(File image)
_userImageFile = image;
void _trysubmit()
final isValid = _formKey.currentState.validate();
FocusScope.of(context).unfocus();
if (_userImageFile == null && !_isLogin)
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('Please Pick an Image'),
backgroundColor: Theme.of(context).errorColor,
),
);
return;
if (isValid)
_formKey.currentState.save();
print(_userEmail);
print(_userPassword);
widget.submitFn(_userEmail.trim(), _userPassword.trim(), _userName.trim(),
_userImageFile, _isLogin, context);
print(_userEmail);
print(_userPassword);
@override
Widget build(BuildContext context)
return Center(
child: Card(
margin: EdgeInsets.all(20),
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
if (!_isLogin)
UserImagePicker(
imagePickFn: _pickedImage,
),
TextFormField(
key: ValueKey('emailAdress'),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Email address',
),
validator: (value)
if (value.isEmpty || !value.contains('@'))
return 'Please return a valid email address';
return null;
,
onSaved: (newValue)
_userEmail = newValue;
,
),
if (!_isLogin)
TextFormField(
key: ValueKey('userName'),
decoration: InputDecoration(labelText: 'Username'),
validator: (value)
if (value.isEmpty || value.length < 4)
return 'Please Enter at least 4 characters';
return null;
,
onSaved: (newValue)
_userName = newValue;
,
),
TextFormField(
key: ValueKey('password'),
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value)
if (value.isEmpty || value.length < 7)
return 'Please Enter at least 7 characters';
return null;
,
onSaved: (newValue)
_userPassword = newValue;
,
),
SizedBox(
height: 12,
),
if (widget.isLoading) CircularProgressIndicator(),
if (!widget.isLoading)
RaisedButton(
onPressed: _trysubmit,
child: Text((_isLogin) ? 'Login' : 'SignUp'),
),
if (!widget.isLoading)
FlatButton(
textColor: Theme.of(context).primaryColor,
child: Text(_isLogin
? 'Create new account'
: 'I already have an account'),
onPressed: ()
setState(()
_isLogin = !_isLogin;
);
,
),
],
),
),
),
),
),
),
);
user_image_picker.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class UserImagePicker extends StatefulWidget
UserImagePicker(this.imagePickFn);
final void Function(File pickedImage) imagePickFn;
@override
_UserImagePickerState createState() => _UserImagePickerState();
class _UserImagePickerState extends State<UserImagePicker>
File _image;
final picker = ImagePicker();
Future<void> getImage() async
final pickedFile = await ImagePicker().getImage(source: ImageSource.camera);
setState(()
_image = File(pickedFile.path);
);
widget.imagePickFn(_image);
@override
Widget build(BuildContext context)
return Column(
children: [
CircleAvatar(
radius: 40,
backgroundColor: Colors.grey,
backgroundImage: _image != null ? FileImage(_image) : null,
),
FlatButton.icon(
onPressed: getImage,
icon: Icon(Icons.image),
label: Text('Add Image'),
textColor: Theme.of(context).primaryColor,
),
],
);
【问题讨论】:
你可以在这里发布你的代码而不是你的 Github 仓库的链接吗?有些人如果看不到您的代码,就会对您的帖子投反对票。 @Uni 我上传了发生错误的文件。或者我需要上传项目的所有文件 使用图像选取器选取的图像在哪里? 我真的不明白哪里错了,我能做些什么来帮助你。你想让我告诉你我是如何将图像上传到 Firebase 存储的吗? 你能告诉我如何将图像上传到 Firebase 存储,仅供经过身份验证的用户使用。@Uni 【参考方案1】:既然你让我教你如何将图片上传到Firebase Storage
,我会告诉你整个过程,包括使用Image Picker
插件。这就是你应该如何使用图像选择器:
class PickMyImage
static Future<File> getImage() async
final image = await ImagePicker().getImage(
source: ImageSource.gallery,
maxHeight: 1500,
maxWidth: 1500,
);
if (image != null)
return File(image.path);
return null;
您可以通过以下方式获取该图像并将其上传到 Firebase 存储:
final File _myImage=await PickMyImage.getImage();
if(_myImage!=null)
final StorageReference firebaseStorageRef = FirebaseStorage.instance
.ref()
.child("user/$_auth.currentUser().uid/i"); //i is the name of the image
StorageUploadTask uploadTask =
firebaseStorageRef.putFile(_myImage);
StorageTaskSnapshot storageSnapshot = await uploadTask.onComplete;
var downloadUrl = await storageSnapshot.ref.getDownloadURL();
if (uploadTask.isComplete)
final String url = downloadUrl.toString();
print(url);
//You might want to set this as the _auth.currentUser().photourl
else
//error uploading
【讨论】:
能否添加firebase storage和imagePicker的插件版本。 这里是:image_picker: ^0.6.7+5 and firebase_storage: ^3.1.6 我认为即使是最新版本也可以在这里使用。 是的,最新版本有效..我解决了这个问题..谢谢【参考方案2】:我遇到的问题是因为我返回文件的 ImagePicker() 函数,然后从相机获取图像,然后将文件传递到 Fire Storage 存储桶。
在 user_image_picker.dart
我写了这个
final pickedFile = await ImagePicker().getImage(source: ImageSource.camera);
而不是我必须写这个
final pickedFile = await picker.getImage(source: ImageSource.camera);
【讨论】:
以上是关于在颤动中将图像从图像选择器保存到firebase存储的主要内容,如果未能解决你的问题,请参考以下文章
在颤动中将应用程序/八位字节流转换为图像/jpeg/png?
无法从 firebase/storage 导入 getStorage 以与 React Native Expo 图像选择器一起使用