1

I am trying to save image upload from the camera or gallery permanently, I am using the image_picker package, and each time I choose a picture for a pfp and click on a different tab it's gone, it only saves it temporarily. this is my code below:

import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
// camera
Future getCameraImage() async{
  // getting the image
  final image = await ImagePicker().pickImage(source: ImageSource.camera);
  if(image == null) return;
//  final imageTemporary = File(image.path);
final imagePerm = await saveImagePermanently(image.path);
 setState(() {
   this.image = imagePerm;
 });
}
// image picker/ gallery
File? image;
 Future getImage() async{
  final image = await ImagePicker().pickImage(source: ImageSource.gallery);
 if(image == null) return;
 final imageTemporary = File(image.path);
 setState(() {
   this.image = imageTemporary;
 });
 }

I have tried a few different methods but run into the same error.

Gwhyyy
  • 7,554
  • 3
  • 8
  • 35
  • what do you mean by permentaly, do you want to download it and save it in the device, or do you mean to save it just across the app screens – Gwhyyy Nov 12 '22 at 16:09
  • I mean by when the user clicks to another nav page they can come back to see their profile image instead of it disappearing when navigating somewhere else in the app. – mellowchest Nov 12 '22 at 20:10
  • oh, then you can simply set the File? image; from the class scope to the global scope, or to a separate class, because setting it inside the state of the widget will be disposed when you navigate, then re built when you return to that page causing it to be lost – Gwhyyy Nov 12 '22 at 20:31
  • Thank you, do you mind giving me a short example? – mellowchest Nov 12 '22 at 20:46
  • I will write an answer for it – Gwhyyy Nov 12 '22 at 20:48

2 Answers2

0

Follow these steps:

  // Step 1: Retrieve image from picker 
final File image = await ImagePicker.pickImage(source: imageSource);

// Step 2: Check for valid file
if (image == null) return;

// Step 3: Get directory where we can duplicate selected file.
final String path = await getApplicationDocumentsDirectory().path;

// Step 4: Copy the file to a application document directory. 
final var fileName = basename(file.path);
final File localImage = await image.copy('$path/$fileName');
aminjafari-dev
  • 264
  • 1
  • 17
  • I have tried that unfortunatley it's still not working I have even imported another path but still the same error, code below: – mellowchest Nov 12 '22 at 19:45
  • File? image; Future getImage(ImageSource source) async{ try{ final image = await ImagePicker().pickImage(source: source); if (image == null) return; final imagePermanent = await saveImagePermanently(image.path); setState(() => this.image = imagePermanent); } on PlatformException catch (e) { print('failed to pick image: $e'); } } – mellowchest Nov 12 '22 at 19:47
  • Future saveImagePermanently(String imagePath) async{ final directory = await getApplicationDocumentsDirectory(); final fileName = basename(imagePath); final image = File('${directory.path}/$fileName'); return File(imagePath).copy(image.path); } – mellowchest Nov 12 '22 at 19:47
0

the StatefulWidget have a lifecycle when navigating between screens in your bottom nav, you're killing the state of widgets that aren't shown on the screen.

so changing to other screens that the one where you pick an image, the File? image; which should have the image file is killed, so when you come back to that screen, that widget is rebuild again which will cause that it's just null and it lost the previous value.

the solution for this is to set that variable on the global scope it's never re-initialized to null, like:

File? image;

class YourStateFulWidget extends StateFulWidget {

 /* all your widget and State object code*/    
Gwhyyy
  • 7,554
  • 3
  • 8
  • 35
  • so would it be something like this? – mellowchest Nov 12 '22 at 21:27
  • import 'package:path/path.dart'; File? image; class BuildProfile extends StatefulWidget { Future getImage(ImageSource source) async{ try{ final image = await ImagePicker().pickImage(source: ImageSource.gallery); if (image == null) return; final imagePermanent = await saveImagePermanently(image.path); setState(() => this.image = imagePermanent); } on PlatformException catch (e) { print('failed to pick image: $e'); } } – mellowchest Nov 12 '22 at 21:28
  • Future saveImagePermanently(String imagePath) async{ final directory = await getApplicationDocumentsDirectory(); final fileName = basename(imagePath); final image = File('${directory.path}/$fileName'); return File(imagePath).copy(image.path); } – mellowchest Nov 12 '22 at 21:30
  • no, you need to simulate changes of this – Gwhyyy Nov 12 '22 at 21:36
  • File? image; class BuildProfile extends StatefulWidget { Future getImage(ImageSource source) async{ try{ image = await ImagePicker().pickImage(source: ImageSource.gallery); if (image == null) return; final imagePermanent = await saveImagePermanently(image.path); setState(() => image = imagePermanent); } on PlatformException catch (e) { print('failed to pick image: $e'); } } – Gwhyyy Nov 12 '22 at 21:36
  • Future saveImagePermanently(String imagePath) async{ final directory = await getApplicationDocumentsDirectory(); final fileName = basename(imagePath); image = File('${directory.path}/$fileName'); return File(imagePath).copy(image.path); } – Gwhyyy Nov 12 '22 at 21:37
  • ok so do I put this in the same file or make a new file and import it into it? – mellowchest Nov 12 '22 at 21:48
  • you can do it in same file, just let File? image; outside the widget class, and replace your methods with those i send in comments – Gwhyyy Nov 12 '22 at 21:53
  • ok so like this? – mellowchest Nov 12 '22 at 21:59
  • File? image; class BuildProfile extends StatefulWidget { const BuildProfile({super.key}); @override State createState() => _BuildProfileState(); } class _BuildProfileState extends State { – mellowchest Nov 12 '22 at 21:59
  • Future getImage(ImageSource source) async{ try{ final image = await ImagePicker().pickImage(source: source); if (image == null) return; final imagePermanent = await saveImagePermanently(image.path); setState(() => this.image = imagePermanent); } on PlatformException catch (e) { print('failed to pick image: $e'); } } – mellowchest Nov 12 '22 at 22:00
  • Future saveImagePermanently(String imagePath) async{ final directory = await getApplicationDocumentsDirectory(); final fileName = basename(imagePath); final image = File('${directory.path}/$fileName'); return File(imagePath).copy(image.path); } – mellowchest Nov 12 '22 at 22:00
  • no instead of the `final image`, just use `image` since it's already defined – Gwhyyy Nov 12 '22 at 22:03
  • ok so this I have updated: – mellowchest Nov 12 '22 at 22:10
  • Future saveImagePermanently(String imagePath) async{ final directory = await getApplicationDocumentsDirectory(); final fileName = basename(imagePath); image = File('${directory.path}/$fileName'); return File(imagePath).copy(image!.path); } – mellowchest Nov 12 '22 at 22:10
  • but i have one error now for this: – mellowchest Nov 12 '22 at 22:11
  • final imagePermanent = await saveImagePermanently(image.path); setState(() => this.image = imagePermanent); } on PlatformException catch (e) { print('failed to pick image: $e'); } – mellowchest Nov 12 '22 at 22:11
  • it says the setter 'image' is not defined for the type _buildProfileState – mellowchest Nov 12 '22 at 22:12
  • can you host the code on dartpad and give me the link – Gwhyyy Nov 12 '22 at 22:14
  • I will make chages and return it back – Gwhyyy Nov 12 '22 at 22:14
  • yes sure : https://gist.github.com/Maryc9/1ba995471e42ff67ff9d36d39a0582be – mellowchest Nov 12 '22 at 22:38
  • try this: https://gist.github.com/anasfik/a6fcbc47920fc9379240fff854ddbddc – Gwhyyy Nov 12 '22 at 22:53
  • just one error : image = await ImagePicker().pickImage(source: source); – mellowchest Nov 12 '22 at 22:59
  • it says a value of XFile? can't be assigned to a variable of type File? – mellowchest Nov 12 '22 at 23:00
  • I've just rectified that error message but now its not uploading the image at all – mellowchest Nov 12 '22 at 23:04