Данная задача часто встречается при разработке мобильного приложения.
Например: требуется создать мобильное приложение, которое будет принимать файлы от пользователя. Для упрощения объяснения, предположим что в приложении будет только «поле для выбора файла» и «кнопка отправить» — максимально простое приложение.
А на сервере будет PHP-код, который обрабатывает входящий HTTP-запрос из Flutter приложения.
Для обработки файлов в мобильном приложении будем использовать библиотеку file_picker. Приблизительный код выбора файлов будет выглядить так (см. пример кода для поля выбора файла внутри мобильного приложения):
Align(<br> alignment: Alignment.bottomRight,<br> child: IconButton<br> onPressed: () {<br> filePick();<br> },<br> icon: const ImageIcon(AssetImage('images/icon_attachment.png'))<br> ),<br> )
Где функция filePick реализована через библиотеку file_picker:
void filePick() async {<br> /// https://pub.dev/packages/file_picker<br> FilePickerResult? result = await FilePicker.platform.pickFiles();<br> <br> if (result != null<br> && result!.files != null<br> && result!.files!.single != null<br> && result!.files!.single!.path != null<br> ) {<br> File file = File(result!.files!.single!.path!);<br> String fileName = file.path.split('/').last;<br> <br> setState(() {<br> _fileName = fileName;<br> _file = file;<br> });<br> <br> } else {<br> // User canceled the picker<br> }<br> }
При вызове filePick() в Android или iOS → откроется встроенный (стандартный) менеджер выбора файлов. После того как файл выбран на основе его расположения создаётся объект File ( из dart::io) и теперь при нажатии на кнопку отправить вызываем HTTP-запрос в который подставим данные из File (_file) в виде Uint8list.
Код HTTP-запроса:
final response = await http.post(<br> Uri.parse('/api/send/file/'),<br> headers: {<br> 'Content-Type': 'application/json',<br> 'Host': 'njsoft.dev'<br> },<br> body: jsonEncode(<string, dynamic=""> {<br> 'flutterUnsigned8integers': _file.readAsBytesSync(),<br> 'file_name': _fileName<br> })<br> ) </string,>
Метод readAsBytesSync возвращает тип Uint8List. Это массив фиксированной длинны из 8-битных целых чисел без знака. Результатом jsonEncode будет json-строка.
Пример:
{<br> "flutterUnsigned8integers":[37,80,68,70,45,49,46,52,10,37,211,235,233,225,10...],<br> "file_name": "выбранный файл.pdf"<br> }
В flutterUnsigned8Integers будет находится массив из чисел. Это будет представление файла в числах. Каждое число это 8-бит, т.е это байт. Следовательно на сервере надо будет выполнить запись байтов в файл.
В PHP где происходит обработка входящего HTTP-запроса, делаем код:
// Обработка запрос POST /api/send/file<br> <br> // Парсинг json<br> $dataFromFlutter=json_decode(file_get_contents('php://input'),true);<br> // Создаём ресурс на входящий файл в бинарном режиме на запись<br> $file=fopen("/path/to/file/".basename($dataFromFlutter['file_name']), "w");<br> // Читаем данные файла — это числа от 0 до 255<br> foreach ($dataFromFlutter['flutterUnsigned8integers'] as $integer) {<br> // Записываем символ в бинарном представлении (8 бит → в байт)<br> fwrite($file, pack('C', $integer));<br> }<br> <br> fclose($file);<br> // Теперь можно работать с файлом
Важный момент это применение функции pack. Если функцию не применить, то в файл запишутся только числа. И файл не будет корректно открываться, а его размер будет больше чем исходный. Ведь в него будут записаны строки чисел.
Поэтому применяем упаковку числа в бинарное представление с помощью pack и с помощью формата «C» — беззнаковый символ. Чтобы понять почему выбран беззнаковый символ обратимся к документации по PHP для типа строки.

И видим что в PHP строка представлена символами, а 1 символ = 1 байту.





