Search code examples
flutterimagedartuploadfilepicker

Filtering image dimension in Flutter


I am a beginner in Flutter development, I have an issue about filtering the size of pixels in image. I have a class that has a function to pick an image from gallery using file_picker, I want to filter the image that user can only upload the image that are 300x300 pixels. I have tried to modify my code, but when I try it, it seems still not working and the image more than 300x300 pixels is still can be uploaded by user. How can I fix this problem? Can anyone help me to find the solution of this problem?

Here is my code:

class UploadImageField extends StatefulWidget {
  const UploadImageField({super.key, required this.onFileSelected});

  final void Function(String filePath) onFileSelected;

  @override
  State<UploadImageField> createState() => _UploadImageFieldState();
}

class _UploadImageFieldState extends State<UploadImageField> {
  String? _fileName;
  File? _selectedFile;

  void _pickFile() async {
    final result = await FilePicker.platform.pickFiles(
      type: FileType.custom,
      allowedExtensions: ['jpg', 'jpeg', 'png'],
    );
    if (result != null && result.files.isNotEmpty) {
      final file = result.files.first;
      if (file.size <= 5 * 1024 * 1024) {
        // Reads file data into a byte array
        final imageBytes = File(file.path!).readAsBytesSync();
        // Decode the image to get dimensions
        final image = img.decodeImage(imageBytes);

        if (image != null && image.width == 300 && image.height == 300) {
          // If the size is appropriate, save the file and send the path to the callback
          setState(() {
            _fileName = file.name;
            _selectedFile = File(file.path!);
          });
          widget.onFileSelected(file.path!);
        } else {
          // If the size does not match, provide an error message
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(
                content: Text('Image must be exactly 300x300 pixels')),
          );
        }
      } else {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('File size exceeds 5MB')),
        );
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          'Dokumen Pendukung',
          style: GoogleFonts.poppins(
            fontSize: 16,
            fontWeight: FontWeight.w500,
          ),
        ),
        const SizedBox(height: 8),
        GestureDetector(
          onTap: _pickFile,
          child: Container(
            height: 150,
            width: double.infinity,
            padding: const EdgeInsets.symmetric(horizontal: 8),
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(8),
              border: Border.all(color: Colors.grey.shade600),
            ),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Icon(Icons.cloud_upload, size: 32, color: Colors.indigo),
                const SizedBox(height: 8),
                Text(
                  _fileName ?? 'Click to upload',
                  style: GoogleFonts.poppins(
                    fontSize: 14,
                    color: Colors.indigo,
                  ),
                ),
                const SizedBox(height: 4),
                Text(
                  'JPEG, JPG, PNG or PDF (max 5MB, 300x300 pixels)',
                  style: GoogleFonts.poppins(
                    fontSize: 12,
                    color: Colors.indigo,
                  ),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}

Solution

  • I have been try your code but it work fine maybe because I'm using decodeImageFromList(Uint8List) Please try this code and tell me is it work for you

    void pickFile() async {
        final result = await FilePicker.platform.pickFiles(
          type: FileType.custom,
          allowedExtensions: ['jpg', 'jpeg', 'png'],
        );
        if (result != null && result.files.isNotEmpty) {
          final file = result.files.first;
          if (file.size <= 5 * 1024 * 1024) {
            final imageBytes = File(file.path!).readAsBytesSync();
            final image = await decodeImageFromList(imageBytes);
            if (image.width == 300 && image.height == 300) {
              log('correct size');
            } else {
              log('image width :: ${image.width}');
              log('image height :: ${image.height}');
              ScaffoldMessenger.of(Get.context!).showSnackBar(
                const SnackBar(content: Text('Image must be exactly 300x300 pixels')),
              );
            }
          } else {
            ScaffoldMessenger.of(Get.context!).showSnackBar(
              const SnackBar(content: Text('File size exceeds 5MB')),
            );
          }
        }
      }