Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter receives 422 response from Fastapi when posting a PNG file

I have created a working localhost API with FastAPI. The POST takes a PNG, does some image processing and returns a PNG as expected when I click the 'try it out' button in the FastAPI generated docs: successful localhost api call for png The curl post command shows as follows:

curl -X 'POST' \
  'http://localhost:8345/api/predict' \
  -H 'accept: application/json' \
  -H 'Content-Type: multipart/form-data' \
  -F 'file=@test_img.png;type=image/png'

The image File is successfully retrieved from the image picker library. (Where the image1 object has been initialized as File image1; in the app page's class.

Future getImage() async {
    var imageTmp = await ImagePicker.pickImage(source: ImageSource.gallery);
    setState(() {
      image1 = imageTmp;
      print('Image Path $image1');
    });
  }

I tried to emulate the API call with the below function in Flutter.

  doUpload() {
    /*
    curl -X 'POST' \
  'http://192.168.178.26:8345/api/predict' \
  -H 'accept: application/json' \
  -H 'Content-Type: multipart/form-data' \
  -F 'file=@test_img.png;type=image/png'

     */
    var request = http.MultipartRequest(
      'POST',
      Uri.parse("http://<my locally hosted ip>:8345/api/predict"),
    );
    Map<String, String> headers = {"Content-type": "multipart/form-data"};
    request.files.add(
      http.MultipartFile(
        'image',
        image1.readAsBytes().asStream(),
        image1.lengthSync(),
        filename: 'filename',
        contentType: MediaType('image', 'png'),
      ),
    );
    request.headers.addAll(headers);
    print("request: " + request.toString());
    request.send().then((value) => print(value.statusCode));
  }

When I run the doUpload() function, a POST is successfully sent to the localhost API, but it returns a 422 error 'unprocessable entity'. What I tried:

  • I tried to set the image type in doUpload to jpg, jpeg, but I keep getting a 422 error.
  • I tried looking up where the image_picker is supposed to store the temporary file to see if it's stored correctly, but when I look at the generated filepath, I don't see the actual file and tmp folder: filepath: File: '/data/user/0/<my package name>/cache/image_picker3300408791299772729jpg'

looking at my local UI filepath, I see: enter image description here

It shows no folder named cache, so I can't inspect it like this. However, the image picker saves it with a jpg at the end (not .jpg, is this normal?)

  • I also tried adding this debugger function to my fastAPI server.py, but I'm not sure how I can inspect the resulting data in the current flutter code: https://fastapi.tiangolo.com/tutorial/handling-errors/#use-the-requestvalidationerror-body The resulting value has properties like statusCode and reason, but I don't see a full json output option.
like image 546
DaReal Avatar asked Dec 16 '25 21:12

DaReal


1 Answers

To mimic that curl command exactly, use this: (I've used the convenience constructor for simplicity)

  final request = http.MultipartRequest(
    'POST',
    Uri.parse('http://<my locally hosted ip>:8345/api/predict'),
  );

  request.files.add(
    await http.MultipartFile.fromPath(
      'file', // NOTE - this value must match the 'file=' at the start of -F
      image1.path,
      contentType: MediaType('image', 'png'),
    ),
  );

  final response = await http.Response.fromStream(await request.send());

  print(response.body);
like image 168
Richard Heap Avatar answered Dec 19 '25 22:12

Richard Heap



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!