1

I'm trying to store an Image that the user will be able to pick from their gallery while submitting a form. Everything works fine. Until I click save, to therefore submit my data I entered into firebase but I keep getting this error:

════════ Exception caught by gesture ═══════════════════════════════════════════
The following JsonUnsupportedObjectError was thrown while handling a gesture:
Converting object to an encodable object failed: Instance of '_File'

Here is how im fetching the data using Firebase:

Future<void> fetchAndSetCars() async {
    const url = '';
    try {
      final response = await http.get(url);
      final extractedData = json.decode(response.body) as Map<String, dynamic>;
      final List<AddCar> loadedCars = [];
      extractedData.forEach((carId, carData) {
        loadedCars.add(AddCar(
          id: carId,
          name: carData['name'],
          city: carData['city'],
          country: carData['country'],
          currencyT: carData['currency'],
          price: carData['price'],
          date: carData['date'],
          sponsNum: carData['sponsNum'],
          category: carData['category'],
          company: carData['company'],
          model: carData['model'],
          year: carData['year'],
          engine: carData['engine'],
          distanceCovered: carData['distanceCovered'],
          transmission: carData['transmission'],
          oilT: carData['oil type'],
          outColor: carData['outter color'],
          inColor: carData['inner color'],
          description: carData['description'],
          address: carData['address'],
          image: carData['image'],
        ));
      });
      _cars = loadedCars;
      notifyListeners();
    } catch (error) {
      throw (error);
    }
  }

  AddCar findById(String id) {
    return _cars.firstWhere((carProd) => carProd.id == id);
  }

  void addCar(AddCar car) {
    const url = '';
    http.post(
      url,
      body: json.encode({
        'name': car.name,
        'city': car.city,
        'country': car.country,
        'currencyT': car.currencyT,
        'price': car.price,
        'sponsNum': car.sponsNum,
        'category': car.category,
        'company': car.company,
        'model': car.model,
        'year': car.year,
        'engine': car.engine,
        'distanceCovered': car.distanceCovered,
        'transmission': car.transmission,
        'oilT': car.oilT,
        'outColor': car.outColor,
        'inColor': car.inColor,
        'description': car.description,
        'address': car.address,
        'image': car.image,
      }),
    );
    final newCar = AddCar(
      id: DateTime.now().toString(),
      name: car.name,
      city: car.city,
      country: car.country,
      currencyT: car.currencyT,
      price: car.price,
      date: car.date,
      sponsNum: car.sponsNum,
      category: car.category,
      company: car.company,
      model: car.model,
      year: car.year,
      engine: car.engine,
      distanceCovered: car.distanceCovered,
      transmission: car.transmission,
      oilT: car.oilT,
      outColor: car.outColor,
      inColor: car.inColor,
      description: car.description,
      address: car.address,
      image: car.image,
    );
    _cars.insert(0, newCar);
    notifyListeners();
  }

using an ImagePicker this is how I wrote the code:

Future<void> _takePicture() async {
    final imageFile = await ImagePicker.pickImage(
      source: ImageSource.gallery,
    );
    setState(() {
      data.image = imageFile;
    });
    final appDir = await syspaths.getApplicationDocumentsDirectory();
    String fileName = path.basename(imageFile.path);
    final savedImage = await imageFile.copy('${appDir.path}/$fileName');
    widget.onSelectImage(savedImage);
  }

here is the button the user clicks on (which works fine)

Column(
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.only(top: 25.0),
                  child: Container(
                    decoration: BoxDecoration(
                      border: Border.all(color: Theme.of(context).primaryColor),
                      borderRadius: BorderRadius.circular(50.0),
                    ),
                    child: FlatButton(
                      child: Text(AppLocalizations.of(context).createAddImages),
                      onPressed: _takePicture,
                    ),
                  ),
                )
              ],
            )

and here is where im displaying the data

class CarsList extends StatefulWidget {
  @override
  _CarsListState createState() => _CarsListState();
}

class _CarsListState extends State<CarsList> {
  var _isInit = true;
  @override
  void didChangeDependencies() {
    if (_isInit) {
      Provider.of<Cars>(context).fetchAndSetCars();
    }
    _isInit = false;
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    final carsData = Provider.of<Cars>(context);
    final car = carsData.cars;
    return car.isEmpty
        ? Center(
            child: Text(
            'لا يوجد سيارات للبيع',
            style: TextStyle(
              fontFamily: ArabicFonts.Tajawal,
              fontWeight: FontWeight.bold,
              package: 'google_fonts_arabic',
            ),
          ))
        : ListView.builder(
            padding: const EdgeInsets.only(bottom: 47.0),
            itemCount: car.length,
            itemBuilder: (ctx, i) => CarItem(
              car[i].id,
              car[i].image,
              car[i].name,
              car[i].model,
              car[i].currencyT,
              car[i].price,
              car[i].distanceCovered,
              car[i].transmission,
              car[i].oilT,
              car[i].year,
              car[i].date,
            ),
          );
  }
}
4

2 回答 2

1

您不能将文件存储在数据库中。但是您可以将文件转换为abase64Encoded并存储它。这是一个代码

       String img;

       static Future<String> FileToB64(File f) async {
          List<int> imageBytes = f.readAsBytesSync();

         return base64Encode(
            imageBytes,
          );
       }

像这样调用方法

   FileToB64(your_image_file).then((d){
      setState((){
         img = d; //base64Decode(d);
           });

        });

使用示例

    final image = await ImagePicker.pickImage(source: ImageSource.camera/*ImageSource.gallery*/,  maxHeight: 1100, maxWidth: 1100);
    FileToB64(image).then((d){
        setState((){
           img = d; 
          });
       //Store img to firebase, you can do it here

    });

您还可以使用Firebase 存储并将链接存储在数据库中。

锄头有帮助。

于 2019-10-26T08:50:12.173 回答
0

您需要使用 Multipart Request 将您的文件上传到 Firebase 服务器或可以将您的文件转换为 Base64 字符串并上传它,请查看此链接 [ https://medium.com/flutterpub/firebase-cloud-storage-and-flutter-fa2e91663b95] [1]

于 2019-10-26T11:25:39.067 回答