0

I have a machine learning model that takes a picture and returns a prediction, I uploaded it to a flask server and tested it on website that I created using HTML and it worked, but when I try to use it with a flutter app I get this error : Unhandled Exception: FormatException: Unexpected character (at character 1) when I try to upload a picture from my application. Also, the statusCode I get is 400 .. These are my codes. Any help would be really appreciated.

This is my python code that I created the flask instance in ( I run it on my cmd when I try to establish a connection using the flutter app)

from flask import Flask, render_template, request, jsonify
import cv2
import numpy as np
import pandas as pd
import tensorflow
from tensorflow import keras
from tensorflow.python.keras import backend as k

app = Flask(__name__)

model = tensorflow.keras.models.load_model('model.h5')


@app.route('/')
def index():
    return render_template("index.html", data="hey")


@app.route("/prediction", methods=["POST"])
def prediction():

    
    img = request.files['img']  
    img.save("img.jpg")
    image = cv2.imread("img.jpg")
    image = cv2.resize(image, (224,224))
    image = np.reshape(image, (1,224,224,3))
    pred = model.predict(image)

    pred = pred > 0.5
    if(pred):
        predd="Malignant"
    else:
        predd="Benign"

    return jsonify({"prediction": predd,})
    
#this ip is my network's IPv4
#(I connected both my laptop and mobile to this WiFi while establishing the connection)
if __name__ == "__main__":
    app.run(debug=False,host='192.168.1.103',port=5000)

And this is the code I used in flutter to establish the connection

  sendImageToServer(File imageFile) async {
    var stream = new http.ByteStream(imageFile.openRead());
    stream.cast();
    var length = await imageFile.length();
    print(length);
    
    //this ip is my network's IPv4 
    //(I connected both my laptop and mobile 
    //to this WiFi while establishing the connection) 

    var uri = Uri.parse('http://192.168.1.103:5000/prediction');
    var request = new http.MultipartRequest("POST", uri);
    var multipartFile = new http.MultipartFile('file', stream, length,
        filename:
            basename(imageFile.path));

    request.files.add(multipartFile);
    request.headers["Content-Type"] = 'multipart/form-data';
    var streamedResponse = await request.send();
    var response = await http.Response.fromStream(streamedResponse);
    
    print(response);

    final Map<String, dynamic> responseJson =
        json.decode(response.toString()) as Map<String, dynamic>;
    print(responseJson.toString());

    pre = responseJson["prediction"];
    print(pre);

    setState(() {
      prediction = pre;
    });
  }

  Future getImage() async {
    final image = await picker.getImage(source: ImageSource.gallery);
    sendImageToServer(File(image.path));

    setState(() {
      fileImage = File(image.path);
      sendImageToServer(fileImage);
    });
  }

Also this is what I get on the cmd when I send the request

192.168.1.108 - - [20/Mar/2021 19:14:39] "←[1m←[31mPOST /prediction HTTP/1.1←[0m" 400 -

1 Answers1

0

Updated Answer

so the exception you got is telling you that the server couldn't understand the request you sent, and i think the problem now is the key you're sending with the request here

var multipartFile = new http.MultipartFile('file', stream, length,
        filename:
            basename(imageFile.path));

in your backend you're using the key "img"

img = request.files['img']  

so these should be the same, try the following

var multipartFile = new http.MultipartFile('img', stream, length,
        filename:
            basename(imageFile.path));

I really hope this will work, also check the following links it might help you understand the problem more,

https://dev.to/carminezacc/advanced-flutter-networking-part-1-uploading-a-file-to-a-rest-api-from-flutter-using-a-multi-part-form-data-post-request-2ekm

and this stackoverflow question

Old Answer

the error message is not clarifying where exactly the error is so do this, adding your code inside a try catch block so you can catch any exception thrown and know what is the error.

try {
sendImageToServer(File imageFile) async {
    var stream = new http.ByteStream(imageFile.openRead());
    stream.cast();
    var length = await imageFile.length();
    print(length);
    
    //this ip is my network's IPv4 
    //(I connected both my laptop and mobile 
    //to this WiFi while establishing the connection) 

    var uri = Uri.parse('http://192.168.1.103:5000/prediction');
    var request = new http.MultipartRequest("POST", uri);
    var multipartFile = new http.MultipartFile('file', stream, length,
        filename:
            basename(imageFile.path));

    request.files.add(multipartFile);
    request.headers["Content-Type"] = 'multipart/form-data';
    var streamedResponse = await request.send();
    var response = await http.Response.fromStream(streamedResponse);
    
     //print(response);//this will print instance of response not the response itself
     // i cleared this a bit so we can trace where the error started from
     print(response.statusCode); // the status code of your response
     print(response.reasonPhrase); // the reason it failed "in case it did"
     print(response.body); // the body of the response -> this what you really interested in

  }
} catch (e,s) {
  // this is your life saver, it will tell you everything 
  // you need to know to trace the error (well mostly :D)
  // note : this will catch any exceptions that is thrown in the code, this not related to the response
  // the (e) is error it self so your should print that to know what is the error
  print(e.toString());
  // the (s) is the stackTrace, it will tell you when and where the error 
  // happened, so you should also print it
  print(e.toString());
}
Michael Soliman
  • 2,240
  • 3
  • 7
  • 20
  • But why did you omit this part of the code " final Map responseJson = json.decode(response.toString()) as Map; print(responseJson.toString()); pre = responseJson["prediction"]; print(pre);" – Jasmin mansi Mar 20 '21 at 19:26
  • we first want to make sure that the request is successful and then we will add it, you should now know more about the error, so kindly add the errors you got – Michael Soliman Mar 20 '21 at 19:34
  • I/flutter (20982): 400 I/flutter (20982): ************************************************************ I/flutter (20982): BAD REQUEST I/flutter (20982): ************************************************************ I/flutter (20982): I/flutter (20982): 400 Bad Request I/flutter (20982):

    Bad Request

    I/flutter (20982):

    The browser (or proxy) sent a request that this server could not understand.

    2 I/flutter (20982): ************************************************************
    – Jasmin mansi Mar 20 '21 at 19:47
  • Kindly update your question with the updated code and error so anyone can help – Michael Soliman Mar 21 '21 at 00:13
  • This worked!! Thank you soooo much it is really appreciated :) – Jasmin mansi Mar 21 '21 at 07:18