Flutter receives 422 response from Fastapi when posting a PNG file
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);
DaReal
Updated on December 21, 2022Comments
-
DaReal over 1 year
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: 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:
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.
-
DaReal over 2 yearsThis worked perfectly, thanks a bunch! It returned
INFO: <my local phone ipv4> - "POST /api/predict HTTP/1.1" 200 OK
I only had additionally change the function todoUpload() async {
due to yourawait
. Which is probably for the better anyway :) -
DaReal over 2 yearsAlso thanks for explaining what made it work, with the
file
comment