Is there something wrong with the way [Flutter Web] sends a request POST message to the API server?

Issue

The open api request I’m trying to use requires an image binary value with content-type of multipart/form-data format.
I know you can’t use dart:io in flutter web. I tried to upload an image in multipart/form-data format to the api server in flutter web while looking at several posts.
However, only a message appeared stating that the image could not be recognized.
This is the last thing I tried to create multipart types in flutter web.

import 'package:dio/dio.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
  PlatformFile? objFile;

  pickImage() async {
    var result = await FilePicker.platform.pickFiles(
      withReadStream: true,
    );
    setState(() {
      objFile = result!.files.single;
    });
    uploadImage();
  }

  uploadImage() async {
    FormData formData = FormData.fromMap({'image' : MultipartFile(test!, objFile!.size, filename: objFile!.name)});
    Dio dio = new Dio();
    var response = await dio.post('API url', data: formData);

  }

I additionally used Multipart.form Bytes from http , Multipart.form Bytes from dio . But the result was the same.

The value checked by the request body through the postman interceptor.

content-type=multipart/form-data;bounary=--dio-boundary-1105759322
----dio-boundary-1105759322
content-disposition: form-data; name="image"; filename="test.jpeg"
content-type: application/octet-stream

ÿØÿÛC


        
%# , #&')*)-0-(0%()(ÿÛC



(((((((((((((((((((((((((((((((((((((((((((((((((((ÿÀŽv"ÿÄÿÄC!1AQaq"‘2¡±#BÁÑR3CðñSbr’á‚Â$&4c“ÿÄÿÄ&!1A2Q"a3BRÿÚ?ù×   „É<$/cŸt8D`aú¦Ä@bálŒZVM„ٔʓTL›eOò¢“
èKÇ(p¢‰¥C’ÄÙ‚Ñx²Ù1Jcœ)B›¢$ ¢‚&
‚7› ˜Žp”{&ÊÀÁAî¤Æ
‚nÈ CØÃêOýÒ›§á$sÊ‚r¡ìLÂ…;"éMI½î«gæV<æ6οÙ%_ƒY®}7Òû€¯MŒ&g¹å|µ£ëÐúc\tÚƵƈúÕ]#kQ‹D/Ÿú·cu9«Hà/¢lÚ–êè·¼&Þt
¯H‚&ɶìÛà®iƒh²SöãÔTs[l›/?[s(’˜¨o€¤Û‹*¥AÖ”ðbUgYR’!äJ!M‹™‹«›î©aÉ*ᕨ4p SÉ…¤)‰ì§=‘âJ» oÙGDRåÌy0—²û r ò€·²?Te8±KSTR8ŹDAååþ7)Oˆk)õ²Qk#Ù€Œ ?DÜû&Ä›„ÍÅ”lQjð¡NÑ%HTWP˜²wýÒc(Ÿð¤ð¢S<*6º>ÊaCœ „Ù0
^J(ª%¢ƒFPm‘^u4^èM‘åL…@#•0Qÿ ºi…32§ÙC•D¿&Èw’ˆº‘Ü"…”<&ýРwP {p ¸DCd¼&ÿ©@¨ˆ› La~¨p¦„)’÷‚ˆº²æÒ›ªĘ̀Šaá€0‹n <ò¦M“YM„    L«=ÕnæÊlªŽÂƒóc„m‚—È™Uó  ªºäªÛ•F†\…}7?¨ªZL`*£è¾ŽÝÌ1¤ÜBúk6­
---------------------------SKIP------------------------------
PTiMÂ!¢(èÊ€YÊÂœ"ÑÂ_T<Ñ5îPp™ð ¨„ôOˤ?¢z\ÂÚ¡½ÐiÊc쨟ÝHŸ¢“3ÝA˜( ‘ÊH›(l€Å¼)Ä‘rEÈ[€‹¬”¼x
W7q?ΣHt®“§¤y\½Ìÿ:ÿÍtÖ§T°AÊÕ\ËZVƒÔPha30%1*¶›Ž!7è¥|f›„îÕQ±„9N6åW,¨^Ù8PHN./Ê€îª2ß*{(l¡™šOU¢Ôå3œ*ꜨŠ‹“3¼$«B*ÌŒS„+EÒ‘Ý VHpV±`²³ó€µgܪ‚#“Ü)À!NPCƒÝIÅԛ–”xý”²™@ ?U‚‹n€å!Œ¦&é*ƒ™¨wÄÖØY¢>«}&ü¢×\Ý?ó*9ç%Òº˜@çò H€¥&ꃒ¤(
‚0O8@@EÎéÊœ@TÕr‚ºT¹ÈÔ7T“2¢ƒœbÅsuOî¶Ô0>‹ŸT|Gô•Óa®ïšÔÇe¤T
he<,¨[ü¶[…·M@ZOˆjtˤÝE© QÿÙ
----dio-boundary-1105759322--

When I use the MultipartFile.fromFile method used in flutter ios, I got the response normally. So I’m pretty sure there must be some mistake or misinformation in the flutter web setup.
Thanks in advance!

Solution

this is how I managed to upload an image to Laravel backend using Flutter Web

import 'dart:io';
import 'package:dio/dio.dart' as dio;
import 'package:file_picker/file_picker.dart';

Future pickupUserImage2() async {
    PlatformFile? objFile;
    var picked = await FilePicker.platform.pickFiles();
    objFile = picked!.files.single;
    String? apiUrl = Get.find<MainController>().apiUrl;
    String url = '';
    if (apiUrl != null) url = apiUrl + 'images';
    List<int> list;
    list = List<int>.from(objFile.bytes!);
    dio.FormData formData = dio.FormData.fromMap({'file': dio.MultipartFile.fromBytes(list, filename: objFile.name)});
    DioNetworking _dio = new DioNetworking();

    dynamic result = await _dio.postData(
      url,
      formData,
      contentType: 'multipart/form-data',
    );
    if (result['status'] == true) {
      showToast(result['message']);
      return ImageModel.Image.fromJson(result['data']);
    }
  }

I added a file using MultipartFile.fromBytes which has the first parameter as List which I created from this method "List.from(objFile.bytes!);"

Notes :

  • ImageModel.Image is a model I created to handle the image result
  • DioNetworking is a class that perform dio requests , I just created it to do the
    authentication stuff
import 'package:dio/dio.dart';
class DioNetworking {
  Dio _dio = new Dio();

Future postData(
    String url,
    dynamic data, {
    String? contentType,
  }) async {

    try {

      Response response = await _dio.post(url,
          data: data,
          options: Options(headers: {
            'content-type': contentType != null ? contentType : 'application/json',
            'Accept': 'application/json',
            // 'Authorization': 'Bearer ${token ?? ''}'
            // other headers
          }));
      if (response.statusCode == 200) {
        dynamic data = response.data;

        return data;
      } else {
        print(response.statusCode);
      }
    } on DioError catch (e) {
      print(e);
      if (e.type == DioErrorType.connectTimeout) {
        return {'status': 'Connect Timed Out'};
      }
      if (e.type == DioErrorType.receiveTimeout) {
        return {'status': 'Receive Timed Out'};
      }
      if (e.type == DioErrorType.response) {
        print(e.response!.data);
        print(e.response!.headers);
      }
    }
  }
}

Answered By – Morad Al-Rowaihi

Answer Checked By – Jay B. (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *