Flutter file_picker returns corrupted file in android

103 Views Asked by At

I'm using file_picker in my flutter project to pick zip file from the folder. During unzipping file I'm getting an error "Unexpected character", so I found that picked file is much smaller than original. If file is taken programmatically from folder - all works fine.

FilePickerResult? result = await FilePicker.platform.pickFiles(type: FileType.custom, allowedExtensions: ['zip'], withData: true);
if (result != null) {
   final File zipFileOne = File(result.files.single.path!);        // picked from  app/cache/file_picker/
   print('==== zipFile from picker: ${zipFileOne.lengthSync()}');  // 13787 - wrong size
}

final dirImportFrom = Directory('$path/Download');
File zipFileTwo = File(dirImportFrom.path + '/MyFile.zip');      // file from original location
print('==== zipFile from folder: ${zipFileTwo.lengthSync()}');   // 1553547 - right size

Permissions WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE is present. Problem with picker appears after migrating to null safety. I'll probably avoid using picker in my project, but will be grateful to get a hint what is going wrong.

1

There are 1 best solutions below

0
K.D.Dilshan On

The issue you're facing could be related to how the file is being read or accessed after being picked by FilePicker. The 'withData: true' option might be causing the file to be read in a different way than when you're accessing it directly from its original location.

To investigate further, you might want to check the contents of the files themselves to see if there's any visible difference in the data when read from the picker versus when read directly from the folder. You can do this by examining the bytes or contents of both files to see if they match or if there are discrepancies...Here's an example of how you can compare the contents of the files:

Look at an example of how you can compare the contents of the files,

// Read contents of the files
List<int> pickerFileBytes = await zipFileOne.readAsBytes();
List<int> folderFileBytes = await zipFileTwo.readAsBytes();

// Compare lengths and contents
print('Picker file length: ${pickerFileBytes.length}');
print('Folder file length: ${folderFileBytes.length}');

// Compare bytes to see if they are identical
bool areIdentical = pickerFileBytes.every((byte) => folderFileBytes.contains(byte));
print('Files are identical: $areIdentical');

This code will read both files into byte arrays and compare their lengths and contents. If they are not identical, it might give you a clue about what's going wrong during the picking process.

If the issue persists, you might also consider checking if there are any compression or file size limitations within the FilePicker package that could cause this discrepancy. Additionally, reaching out to the package's maintainers or checking their documentation or issue tracker might provide insights into any known issues related to picking zip files.

Look at full code segment,

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late FilePickerResult? result;
  late File zipFileOne;
  late File zipFileTwo;

  Future<void> pickFile() async {
    result = await FilePicker.platform.pickFiles(
      type: FileType.custom,
      allowedExtensions: ['zip'],
      withData: true,
    );

    if (result != null) {
      zipFileOne = File(result!.files.single.path!);
      print('==== zipFile from picker: ${zipFileOne.lengthSync()}');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('FilePicker Test'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () async {
                await pickFile();
                final dirImportFrom = Directory('$path/Download');
                zipFileTwo = File(dirImportFrom.path + '/MyFile.zip');
                print('==== zipFile from folder: ${zipFileTwo.lengthSync()}');

                // Read contents of the files
                List<int> pickerFileBytes = await zipFileOne.readAsBytes();
                List<int> folderFileBytes = await zipFileTwo.readAsBytes();

                // Compare lengths and contents
                print('Picker file length: ${pickerFileBytes.length}');
                print('Folder file length: ${folderFileBytes.length}');

                // Compare bytes to see if they are identical
                bool areIdentical =
                    pickerFileBytes.every((byte) => folderFileBytes.contains(byte));
                print('Files are identical: $areIdentical');
              },
              child: Text('Compare Files'),
            ),
          ],
        ),
      ),
    );
  }
}