Flutter form with attachment (file upload) - flutter

I am trying to build a Flutter form with 2 text fields and 1 field for an attachment:
Text Field 1
Text Field 2
Attachment
Send Data Button
This is to make a POST request and send these 3 values to my server, store the file locally and get the name of the file in the database. This backend logic is already covered.
I was trying to use a MultiPart request as follows:
Future makePostRequest(
String title, int subjectid, int teacherid, String limitDate) async {
var url = Uri.parse('http://localhost:8000/newHomework');
var request = http.MultipartRequest('POST', url);
var headers = {'Content-Type': 'text/plain; charset=UTF-8'};
print(this.file);
Uint8List data = await file.readAsBytes();
List<int> list = data.cast();
request.files
.add(http.MultipartFile.fromBytes('text', list, filename: 'tarea1'));
request.headers.addAll(headers);
request.fields['title'] = title;
request.fields['limitDate'] = limitDate;
request.fields['subjectid'] = subjectid.toString();
request.fields['teacherid'] = teacherid.toString();
request.fields['ext'] = '.txt';
var res = await request.send();
return res.stream.bytesToString().asStream().listen((event) {
var parsedJson = json.decode(event);
print(parsedJson);
});
}
But I do not know how to do this:
Include a button in the form to add the attachment (will only be text files, and only 1 file always) and then send all of this information with the Send Data Button.
Maybe I am approaching this from an incorrect perspective... Any ideas on how to do this?
Update makePostRequest method, now getting error: Error: NoSuchMethodError: 'readAsBytes'

Related

Flutter send signature image to GCP bucket but file is not usable

I am trying to send a signature from flutter to a GCP Storage bucket.
Currently, I can send a file to the bucket but it's not openable.
Here is what I am using to get base64 format which I supposed is the intended format to send files.
final data = await _signaturePadKey.currentState!
.toImage(pixelRatio: 3.0);
final image = await data.toByteData(
format: ui.ImageByteFormat.png);
// To send
final base64String =
base64.encode(image!.buffer.asUint8List());
setState(() => {_signatureFile = base64String});
Then I am sending my request as :
Future postOKTrackingSignature(String signature, String projectID) async {
await refreshSTSToken(projectID);
String token = await getSTSToken();
// Headers
var headersData = {
"Authorization": "Bearer $token",
"Content-Type": "image/png"
};
// URL building
var resourcePart =
"XXX";
var paramsData = {
'uploadType': 'multipart',
'name': "${resourcePart}signature.png",
};
var baseURI = 'https://storage.googleapis.com/upload/storage/v1/b/';
String bucketName = "XXX";
var query = paramsData.entries.map((p) => '${p.key}=${p.value}').join('&');
// Body
var bodyData = signature;
final response = await http.post(
Uri.parse("$baseURI$bucketName/o?$resourcePart$query"),
headers: headersData,
body: bodyData);
switch (response.statusCode) {
case 200:
print("$baseURI$bucketName/o?$resourcePart$query");
return {"statusCode": response.statusCode};
default:
print("$baseURI$bucketName/o?$resourcePart$query");
return {"statusCode": response.statusCode, "error": response.body};
}
}
Sadly, I the file got upload but is not usable when I want to get preview, or even download it and try to open it. But while I change the extension to .txt, take the string to : https://base64.guru/converter/decode/file it show me my image a png.
I also tried this :
var dataPrepation = base64.normalize(signature);
var bodyData = "data:image/png;base64,$dataPrepation";
String example :
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
Consider Firebase Storage instead of base64; this stackoverflow topic compares the two and outlines the benefits of each.
In light of this, I strongly advise you to continue working on your project utilizing Firebase Storage.
Now, to Upload a file to Cloud Storage, you first create a reference to the full path of the file, including the file name.
// Create a storage reference from our app
final storageRef = FirebaseStorage.instance.ref();
// Create a reference to "mountains.jpg"
final mountainsRef = storageRef.child("mountains.jpg");
// Create a reference to 'images/mountains.jpg'
final mountainImagesRef = storageRef.child("images/mountains.jpg");
// While the file names are the same, the references point to different files
assert(mountainsRef.name == mountainImagesRef.name);
assert(mountainsRef.fullPath != mountainImagesRef.fullPath);
Additionally, I would suggest you review the guide for Firebase Cloud Storage in Flutter written by Dane Mackier.

Convert raw http POST to data, write to file in Flutter

I'm running a web server instance in my Flutter app in order to run an image conversion tool, written in JavaScript. The JS code sends a POST command along with a body which contains the raw image data.
Using httpServer and VirtualDirectory, I'm serving all of the required files if JS calls GET, and now when it calls the POST command, I need to convert the POST request to raw data and save it to a file, as it contains the image data I need.
The current web server logic is written in Python. It uses rfile.read in order to write the data from the request into a file.
contentLength = int(self.headers['Content-Length'])
open("output_files/output.%03d.jpg"%frame,"wb").write(self.rfile.read(contentLength))
This is what I'm trying to recreate in Flutter. Here's my code so far.
_startServer({required String basePath}) async {
var server = await HttpServer.bind(InternetAddress.loopbackIPv4, 8080);
virDir = VirtualDirectory('$tempDir/converter/')
..allowDirectoryListing = true;
debugPrint(
"Server running on IP : ${server.address} On Port : ${server.port}");
await for (var request in server) {
switch (request.method) {
case 'GET':
String path = request.uri.toString();
if (!path.contains(basePath)) {
path = basePath + request.uri.toString();
}
debugPrint('request uri: $path');
final File file = File(path);
if (await file.exists()) {
request.response.statusCode = HttpStatus.ok;
virDir?.serveFile(file, request);
} else {
debugPrint('Could not find: $file');
request.response.statusCode = HttpStatus.notFound;
}
break;
case 'POST':
debugPrint('Content Length: ${request.headers.contentLength}');
debugPrint('Content Type: ${request.headers.contentType}');
final File image =
File('$basePath/videos/frame.${intFixed(frame, 3)}.jpg');
if (!image.existsSync()) {
request.response.statusCode = HttpStatus.ok;
request.response.write('Finished');
request.response.headers.contentType = ContentType.text;
request.response.headers.contentLength = 'Finished'.length;
await request.response.close();
return;
}
final File newImage =
File('$basePath/output_files/output.${intFixed(frame, 3)}.jpg');
ByteData data = ByteData(request.headers.contentLength);
final buffer = data.buffer;
await newImage.writeAsBytes(
buffer.asUint8List(0, request.headers.contentLength));
frame++;
debugPrint('$frame');
request.response.statusCode = HttpStatus.ok;
request.response.headers.contentType = ContentType.text;
request.response.headers.contentLength = "Success".length;
request.response.write("Success");
await request.response.close();
}
}
}
Specifically, this part:
ByteData data = ByteData(request.headers.contentLength);
final buffer = data.buffer;
await newImage.writeAsBytes(
buffer.asUint8List(0, request.headers.contentLength));
When I set a breakpoint and check data, there's no data per-se. Just a list of zeros.
How do I convert the POST request to raw in order to save it to a file? The content length and the content type is correct (image/jpeg), but getting it to data is really stumping me.
After a lot of trial and error, the solution is to use await request.single which outputs a Uint8List, then write that to file as it's a stream of the HTTPRequest object itself.
https://api.flutter.dev/flutter/dart-async/Stream/single.html
final data = await request.single;
final file = File('$basePath/output_files/output.${intFixed(frame, 3)}.jpg');
file.writeAsBytesSync(data);

How to Send an Audio file (.wav) from My Flutter Application to a Flask Server Instance?

I have a machine learning model that is saved as .h5 and used in a flask server. The server is supposed to take an audio file as input and return a prediction string.
My Flask server code:
#app.route("/predict", methods=["POST"])
def predict():
# get file from POST request and save it
audio_file = request.files["file"]
file_name = str(random.randint(0, 100000)) # generate file name as a dummy random number
#wav_filename = str(random.randint(0, 100000))
audio_file.save(file_name)
# instantiate keyword spotting service singleton and get prediction
kss = Keyword_Spotting_Service() # Where our model is hold
predicted_emotion = kss.predict(file_name)
# we don't need the audio file any more - let's delete it!
os.remove(file_name)
# send back result as a json file (dictionary)
result = {"emotion": predicted_emotion}
return jsonify(result)
I tested my server using python client and it worked.
in my flutter app I created a predict method:
final uri = Uri.parse('http://192.168.1.14:5000/predict');
final request = new http.MultipartRequest("POST", uri);
request.fields['audio'] = "audio";
//myStreamController.stream.asBroadcastStream().listen(request);
final multipartFile = new http.MultipartFile.fromBytes('file', (await rootBundle.load("assets/audioFile.wav")).buffer.asUint8List( ), filename: 'audioFile.wav');
request.files.add(multipartFile);
request.headers["Content-Type"] = 'multipart/form-data';
final streamedResponse = await request.send();
// final x = await streamedResponse.stream.toBytes();
Response response = await http.Response.fromStream(streamedResponse);
Map<String, dynamic> result = jsonDecode(response.body);
var resultx = jsonDecode(json.encode(response.body));
predic = "${resultx['emotion']}";
// resultx.clear();
return predic;
It keeps giving me this error: File contains data in an unknown format (Runtime Error).
What am I missing?
Any help will be highly appreciated.

Line after await http response in Flutter app does not execute

I want to fetch a result from Flask API after sending http.MultipartFile request to server.
like this:
Future<String> upload(List<int> filename, String url) async {
//filename : binary conversion of string
//String url : api address
print("Inside Upload future!");
var request = http.MultipartRequest('POST', Uri.parse(url));
request.files.add(
http.MultipartFile.fromBytes('file', filename, filename: 'files.txt'));
print("Sending Request!");
http.Response response = await http.Response.fromStream(await request.send());
print("request sent! now returning");
var rtr = response.body;
return rtr;
}
But the problem is it does not return, and output after execution is The print after await is not executed why??:
Inside Upload future!
Sending Request!
I am sending a String to Flask API like:
It works correctly, it is receiving a string and then replying with the same string with some modifications.
#app.route('/test_api', methods=['GET', 'POST'])
def test_api():
uploaded_file = request.files['file']
file_content = uploaded_file.read().splitlines()
uploaded_file.seek(0)
file_pretty = uploaded_file.read()
a = runkey(file_pretty)
//takes string agrument and returns manipulated string
uploaded_file.seek(0)
filename = secure_filename(uploaded_file.filename)
resp = make_response(a)
resp.headers['Content-Type'] = 'text/plain;charset=UTF-8'
n = filename
resp.headers['Content-Disposition'] = 'attachment;filename='+'n'
return resp ```
I Solved this, By Adding
resp.headers['Access-Control-Allow-Origin'] = '*'
//before returning response to client
to the FlaskAPI response.
actually, I thought there's an error in Dart somewhere. But it was hiding in Chrome debugging, Since I am using Flutter Web.
The error is of Cross-Origin not allowed due to access control.

How send data to php file With Post

I am new in flutter and I want to send data(id in my program) to a php file and get it with $_POST ,and then send the result back but the Solution's that i have found didn't work .
I think my body is wrong , I tried to change body to a
Map<String,dynamic>
but its didn't work.
Future<List<dynamic>> getData() async {
String body = "{'id' : 1}" ;
String url = "http://10.0.2.2:8080/facts/get.php";
http.Response responseData = await http.post(
url
,body: body);
print(responseData.body);
return json.decode(responseData.body);
}