BraveEvidence
BraveEvidence

Reputation: 35

How to set Timeout for MultiPart Request in Dart?

Here is my MultiPartRequest code

var request =
            http.MultipartRequest("POST", Uri.parse(EMPLOYEE_PUNCH_IN_URL));

        request.fields['uid'] = userId;
        request.fields['location'] = location;
        request.fields['punchin_time'] = punchInTime;
        request.fields['punchin_location_name'] = address;

        var multiPartFile = await http.MultipartFile.fromPath(
            "photo", imageFile.path,
            contentType: MediaType("image", "$extension"));
        request.files.add(multiPartFile);
        http.StreamedResponse response = await request.send();

        var responseByteArray = await response.stream.toBytes();

        employeePunchInModel = standardSerializers.deserializeWith(
            EmployeePunchInModel.serializer,
            json.decode(utf8.decode(responseByteArray)));
        ......

I know how to set timeout to a normal http request. I have followed this link

Set timeout for HTTPClient get() request

I have tried adding timeout function in following ways but it won't work and my request gets completed

1.

 var multiPartFile = await http.MultipartFile.fromPath(
            "photo", imageFile.path,
            contentType: MediaType("image", "$extension")).timeout(const Duration(seconds: 1)); 

2.

http.StreamedResponse response = await request.send().timeout(const Duration(seconds: 1));

3.

var responseByteArray = await response.stream.toBytes().timeout(const Duration(seconds: 15));

But none of the above timeout works.

Upvotes: 2

Views: 3651

Answers (5)

hasToDev
hasToDev

Reputation: 21

Using http package, this is my approach :

  1. Create a Streamed Response that we're going to use for onTimeOut callback
StreamedResponse timeOutResponse({
  @required String httpMethod,
  @required dynamic error,
  @required String url,
}) { 
  Map<String, dynamic> body = {
    'any': 'value',   
    'you': 'want for $error',
  };

  int statusCode = 404;  
  Uri destination = Uri.parse(url);
  String json = jsonEncode(body);
  
  return StreamedResponse(
    Stream.value(json.codeUnits),
    statusCode,
    request: Request(httpMethod, destination),
  );
}
  1. Use the modified http multipart function from Mahesh Jamdade answer
Future<http.Response> makeAnyHttpRequest(String url,
  Map<String, dynamic> body,
  {Function onTimeout,
  Duration duration = const Duration(seconds: 10)}) async {

     final request = http.MultipartRequest(
         'POST',
          Uri.parse('$url'),
       );
     
     final res = await request.send().timeout(
         duration,
         onTimeout: () {
           return timeOutResponse(
             httpMethod: 'MULTIPART POST',
             error: 'Request Time Out',
             url: url,
           );
         },
       );

     return await http.Response.fromStream(res);
  }

this way, instead of timeout exception, you can return the onTimeOut Http Response.

Upvotes: 2

Mahesh Jamdade
Mahesh Jamdade

Reputation: 20231

You can try this which uses http package

declare your multipart function like this with your desired arguments

 Future<http.Response> makeAnyHttpRequest(String url,
      Map<String, dynamic> body,
      {Function onTimeout,
      Duration duration = const Duration(seconds: 10)}) async {
    final request = http.MultipartRequest(
      'POST',
      Uri.parse('$url'),
    );
    final res = await request.send().timeout(duration, onTimeout: onTimeout);
    return await http.Response.fromStream(res);
  }

and then call it within a try catch block and you can catch the timeout exception by throwing the desired value on Timeout.

try{
    final res = makeAnyHttpRequest("<url>",{"body":"here"},onTimeout:(){
      throw 'TIME_OUT'; // Throw anything
    });
      
  }catch(_){
      if (_.toString() == 'TIME_OUT') { // catch the thrown value to detect TIMEOUT
        /// DO SOMETHING ON TIMEOUT    
          debugPrint('The request Timeout');   
     }
  }
}

The above approach would work for any http request as long as you have a onTimeout call back

Upvotes: 0

Yousif khalid
Yousif khalid

Reputation: 6465

I suggest that

var request = http.MultipartRequest("POST", Uri.parse(EMPLOYEE_PUNCH_IN_URL));

  request.fields['uid'] = userId;
  request.fields['location'] = location;
  request.fields['punchin_time'] = punchInTime;
  request.fields['punchin_location_name'] = address;

  var multiPartFile = await http.MultipartFile.fromPath(
      "photo", imageFile.path,
      contentType: MediaType("image", "$extension"));
  request.files.add(multiPartFile);

  await request.send().timeout(Duration(seconds: 1), onTimeout: () {
    throw "TimeOut";
  }).then((onValue) {
    var responseByteArray = await onValue.stream.toBytes();

    employeePunchInModel = standardSerializers.deserializeWith(
        EmployeePunchInModel.serializer,
        json.decode(utf8.decode(responseByteArray)));
  }).catchError((){ throw "TimeOut";});

Upvotes: 1

Dharmesh Mansata
Dharmesh Mansata

Reputation: 4728

Use Dio package with following code:

  try {
  final response = await Dio().post(requestFinal.item1, data:formData, options: option,
      onSendProgress: (sent, total) {
        print("uploadFile ${sent / total}");
      });

  print("Response Status code:: ${response.statusCode}");

  if (response.statusCode >= 200 && response.statusCode < 299) {

    dynamic jsonResponse = response.data;
    print("response body :: $jsonResponse");
    final message = jsonResponse["msg"] ?? '';
    final status = jsonResponse["status"] ?? 400;
    final data = jsonResponse["data"];
    return HttpResponse(status: status, errMessage: message, json: data);
  }
  else {
    dynamic jsonResponse = response.data;
    print('*********************************************************');
    print("response body :: $jsonResponse");
    print('*********************************************************');
    var errMessage = jsonResponse["msg"];
    return HttpResponse(status: response.statusCode, errMessage: errMessage, json: jsonResponse);
  }
}
on DioError catch(error) {
  print('*********************************************************');
  print('Error Details :: ${error.message}');
  print('*********************************************************');
  dynamic jsonResponse = error.response.data;
  print('*********************************************************');
  print("response body :: $jsonResponse");
  print('*********************************************************');
  var errMessage = jsonResponse["message"] ?? "Something went wrong";
  return HttpResponse(status: jsonResponse["status"] , errMessage:  errMessage, json: null);
}                                                                                      

Hope this helps!

Upvotes: 1

Jaspalsinh Gohil
Jaspalsinh Gohil

Reputation: 704

hey you can also use dio 3.0.4

A powerful Http client for Dart, which supports Interceptors, Global configuration, FormData, Request Cancellation, File downloading, Timeout etc.

Here is the link :Http client for Dart

Upvotes: 0

Related Questions