如何在 Firestore 集合 flutter 中上传图片

How to upload images in Firestore collection flutter

我有一个用户个人资料表格,我希望将个人资料图像与用户的其他信息一起存储在 firestore 中!我做了存储信息的部分,但不知道如何将图像存储在同一个文档中! 你能帮我么 ? 我的代码只能选择图片,我没有集成存储在firestore中的部分

const kTextFieldDecoration = InputDecoration(
  hintText: 'Enter a value',
  hintStyle: TextStyle(color: Colors.grey),
  contentPadding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
  border: OutlineInputBorder(
    borderRadius: BorderRadius.all(Radius.circular(32.0)),
  ),
  enabledBorder: OutlineInputBorder(
    borderSide: BorderSide(color: Color(0xff5AA7A7), width: 1.0),
    borderRadius: BorderRadius.all(Radius.circular(32.0)),
  ),
  focusedBorder: OutlineInputBorder(
    borderSide: BorderSide(color: Color(0xff5AA7A7), width: 2.0),
    borderRadius: BorderRadius.all(Radius.circular(32.0)),
  ),
);


class Background extends StatefulWidget {
   final Widget child;
   
  const Background({
    Key? key,
    required this.child,
  }) : super(key: key);
  @override
  _BackgroundState createState() => _BackgroundState();
}
class _BackgroundState extends State<Background>{
final _auth = FirebaseAuth.instance;
final _firebaseStorage = FirebaseStorage.instance ; 


uploadImage() async {
  Reference ref = _firebaseStorage.ref().child('profileimage');
  UploadTask uploadTask = ref.putFile(imageFile); 
  var imageUrl = await ( await uploadTask).ref.getDownloadURL();
  setState(() => {
     imageurl=  imageUrl.toString()
  });
}
 
  late File imageFile;
  late String name;
  late DateTime birth ; 
  late String pass ; 
  late String? genre ;
  
  TextEditingController dateinput = TextEditingController(); 
  
final List<String> genderItems = [
  'Male',
  'Female',
];
String? selectedValue;
  
  final ImagePicker _picker = ImagePicker();
  bool showSpinner = false;
 
  static final DateFormat format = DateFormat('yyyy-MM-dd');
  
  File? imagePicked;
  late Future<PickedFile?> pickedFile = Future.value(null);
  String? imageurl ; 




// Pick Image From Gallery
_getFromGallery() async {
    final picker = ImagePicker();
    final pickedImage = await picker.pickImage(
      source: ImageSource.gallery,
    );
    final pickedImageFile = File(pickedImage!.path);
    setState(() {
      imagePicked = pickedImageFile;
    });
  
}

 
  

    void addPatient() {
  FirebaseFirestore.instance.collection("patient").add(
  {
    
    "name" : name,
    "genre" : genre,
    "birth" : birth,
    "pass" : pass,
  }).then((value){
    print("Patient data Added");
    

  });
}
  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    
    return Scaffold(
      resizeToAvoidBottomInset: false ,
      backgroundColor: Colors.white,
      body: ModalProgressHUD(
        inAsyncCall: showSpinner,
       child: SingleChildScrollView(   
      child: Padding(
        
         padding: EdgeInsets.symmetric(horizontal: 24.0),
         child: Column(
            
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            
        children: <Widget>[
          

          Container(
            
            child : CircleAvatar(
            radius: 70.0,
            backgroundColor: Colors.grey,
            backgroundImage: imagePicked == null
                              ? null
                              : FileImage(
                                  imagePicked!,
                                ),
          ),
            
          ),
          
          Container(
            padding: EdgeInsets.only( left: 100.0),
                child : Positioned(
                        bottom: 50.0,
                        right: 20.0, 
                        
                        child: InkWell(
                          onTap: () {
                           _getFromGallery();
                              },
                        child: Icon(
                          Icons.camera_alt_outlined, 
                          size:28.0,color: 
                          Colors.teal,
                           ),
                            ),
                 ), ),
         
               SizedBox(
                height: 25.0,
              ),
              
               
               SizedBox(
                height: 8.0,
              ),
              TextField(
                  keyboardType: TextInputType.text,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    name = value;
                  },
                  decoration: kTextFieldDecoration.copyWith( 
                      labelText: 'Name')),
              SizedBox(
                height: 8.0,
              ),
              
              SizedBox(
                height: 8.0,
              ),
              TextField(
                  obscureText: true,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    pass = value ;
                  },
                  decoration: kTextFieldDecoration.copyWith(
                      labelText: 'Password',)),
                      SizedBox(
                height: 8.0,
              ),
              
              SizedBox(
                height: 8.0,
              ),
             Column(
               children: [
                   DropdownButtonFormField(
              decoration: 
                //Add isDense true and zero Padding.
                //Add Horizontal padding using buttonPadding and Vertical padding by increasing buttonHeight instead of add Padding here so that The whole TextField Button become clickable, and also the dropdown menu open under The whole TextField Button.
                InputDecoration(
          
         hintStyle: TextStyle(color: Colors.grey),
         contentPadding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
         border: OutlineInputBorder(
           borderRadius: BorderRadius.all(Radius.circular(32.0)),
         ),
         enabledBorder: OutlineInputBorder(
           borderSide: BorderSide(color: Color(0xff5AA7A7), width: 1.0),
           borderRadius: BorderRadius.all(Radius.circular(32.0)),
         ),
         focusedBorder: OutlineInputBorder(
           borderSide: BorderSide(color: Color(0xff5AA7A7), width: 2.0),
           borderRadius: BorderRadius.all(Radius.circular(32.0)),
         ),
                //Add more decoration as you want here
                //Add label If you want but add hint outside the decoration to be aligned in the button perfectly.
               labelText: 'Gender',

              ), 
                 isExpanded: true,
                 
                   
                   icon: const Icon(
                Icons.arrow_drop_down,
                color: Colors.teal,
              ), 
               iconSize: 30,
              
              items: genderItems
                      .map((item) =>
                      DropdownMenuItem<String>(
                        value: item,
                        child: Text(
                          item,
                          style: const TextStyle(
                            fontSize: 14,
                          ),
                        ),
                      ))
                      .toList(),
              validator: (value) {
                if (value == null) {
                  return 'Please select gender.';
                }
              },  
               onChanged: (value) {
                genre = value as String? ; //Do something when changing the item if you want.
              },
              onSaved: (value) {
                selectedValue = value.toString();
              },
            ),   
               ],
             ), 

                      SizedBox(
                height: 8.0,),
                      
              SizedBox(
                height: 8.0,
              ),
              TextField(
                       controller: dateinput,
                       textAlign: TextAlign.center,
                       readOnly: true,
                       
                       decoration: InputDecoration( 
                     
                    hintStyle: TextStyle(color: Colors.grey),
                 contentPadding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
                 border: OutlineInputBorder(
                   borderRadius: BorderRadius.all(Radius.circular(32.0)),
                 ),
                 enabledBorder: OutlineInputBorder(
                   borderSide: BorderSide(color: Color(0xff5AA7A7), width: 1.0),
                   borderRadius: BorderRadius.all(Radius.circular(32.0)),
                 ),
                 focusedBorder: OutlineInputBorder(
                   borderSide: BorderSide(color: Color(0xff5AA7A7), width: 2.0),
                   borderRadius: BorderRadius.all(Radius.circular(32.0)),
                 ),
                    //icon of text field
                  labelText: "Date of Birth" ,  //label text of field
               
               
                ), 

                  onTap: () => BottomPicker.date(
                  
                    minDateTime: DateTime(1900), 
                       maxDateTime: DateTime.now(), 
                       dateOrder: DatePickerDateOrder.dmy , 
                       bottomPickerTheme: BOTTOM_PICKER_THEME.morningSalad,
                       closeIconColor:  Colors.teal,
                       
                  title: "Set your Birthday",
                 titleStyle: const TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 15,
                    color: Colors.teal,
                 ),
                  onSubmit: (value) {
                   
                    dateinput.text = '$value'; 
                    birth = value ;
                    
                  } ,
                ).show(context),
              ),
 RoundedButton(
                colour: Color(0xff96D7C6),
                title: 'Submit',
                onPressed: () async {
                  setState(() {

                    showSpinner = true;
                    addPatient();
                  });
                  Navigator.pushNamed(context, 'patient_screen');
                }, ),],),),),),);}}

您可以使用 Firebase 存储(firebase_storage ) to upload the image file and then you store the download url of the image inside the document in the Cloud Firestore ( cloud_firestore)。

这里是使用Firebase Storage with Flutter, Inside you can find a section that explains the steps to upload files, and another to get the download URL.

的官方文档