Dio - Flutter Image Upload returning Socket Exception - sockets

I have tried uploading image using formData which Dio plugin supports.
FormData formData = new FormData.from(
{"profile_image": UploadFileInfo(image, "profile_image.jpg")});
var response = await _dio.post(ApiConfiguration.getUploadImageUrl().toString(),data: formData);
But its returning error.
DioError [DioErrorType.DEFAULT]: SocketException: OS Error: Connection reset by peer, errno = 54, address = 3.122.199.93, port = 62181
Any help would be appreciated.

UploadFileInfo and FormData.from deprecated in v3. Documentation needs to be clearer and updated. I wasted a good part of a day with this.
I used dio for post a file path with some other information in this way :
Dio dio = new Dio();
FormData formData = new FormData();
formData.add(
"apiKey",
"my_api_key",
);
formData.add(
"file",
"image_path",
);
Response response = await dio.post(
"https://localhost",
data: formData,
onSendProgress: (int sent, int total) {
// do something
},
).catchError((onError) {
throw Exception('something');
});

Faced something similar in Release version of the app, Dio was failing to upload images. This could be due to two reasons, one is mentioned above that you are using a deprecated methods in v3 or You can try adding this permission to the Manifest
Add this permission
<uses-permission android:name="android.permission.INTERNET" />
to your app level Manifest.
android/app/src/main/AndroidManifest.xml
Solution can be found here
https://stackoverflow.com/a/59392036/14641365
Although the other work around to upload an image to the server that I used is something as follows
String url = "YOUR_URL_TO_UPLOAD";
FormData formData = FormData.fromMap({
"QUERY_PARAM_NAME": await MultipartFile.fromFile("IMAGE_PATH", filename:"TESTING.jpg"),
});
var response = await dio.post(url, data: formData);

Related

Flutter http 400 error when sending an XFile Image

I want to send a jpg file from my flutter app to .Net backend. I'm using http package.
My code is as follows:
var uri = Uri.parse('$url/upload/$id');
var request = http.MultipartRequest('POST', uri);
var headers = {'accept': '*/*', 'Content-Type': 'multipart/form-data'};
request.headers.addAll(headers);
var x = await file.readAsBytes();
var mFile = http.MultipartFile.fromBytes('file', x);
request.files.add(mFile);
var response = await request.send();
Here file is an XFile file from package cross_file.
Unfortunately I get an error code - 400 "Bad request".
On the backend side code looks as follows
[HttpPost("/upload/{id}")]
public IActionResult UploadImage(IFormFile imageFormFile, [FromRoute] Guid id)
{
// program does not even enter the function
}
I've tested this using Swagger and it works, it generates following curl:
curl -X 'POST' \
'http://localhost:44383/apiname/f7765448-be93-4e72-b62e-04623b4ccdb1' \
-H 'accept: */*' \
-H 'Content-Type: multipart/form-data' \
-F 'imageFormFile=#sample.jpg;type=image/jpeg'
I've searched some forums and tutorials, but nothing works.
I've tried adding the file using fromBytes, fromPath and fromString, none worked.
I've tried experimenting with different combinations of headers and fields, this didn't work either. In particular I've tried to add fields "imageFormFile" and "type", as in Swagger curl, but it didn't work as well.
I've also tried to rewrite this using dio, but got the same result (also I'd rather stick to http, as the rest of my project uses it).
Future uploadRequest(String url, String filePath) async {
final dio = Dio();
dio.options.contentType = "multipart/form-data";
final multiPartFile = await MultipartFile.fromFile(
filePath,
filename: filePath.split('/').last,
);
FormData formData = FormData.fromMap({
"file": multiPartFile,
});
final response = await dio.post(
url,
data: formData,
);
return response.data;
}
This is 100% working solution but with dio package as I prefer it over http. But It doesn't mean that with http it is impossible.
IMPORTANT: formData could be different according to your API

How to download a .pdf file from an URL with POST Request having a body and headers in Flutter?

I am trying to download a .pdf file from an URL having a POST request with body in Flutter.
I am using Dio plugin for network calls.
Here is what I tried to do so far:
Dio dio = Dio();
late Response response;
Future<APIResponse> downloadFile({token}) async {
await dio
.post('https://www.example.com/sample/download',
data: {
{"month": "January", "year": "2022"}
},
options: Options(
headers: {
'Authorization': 'Bearer $token',
},
))
.then((value) {
if (value.statusCode == 200) {
response = value;
// here I need the file to be downloaded
// specific folder would be /downloads folder in Internal Storage
}
});
return APIResponse.fromJson(response.data);
}
But Dio doesn't have POST method with download option, as far as I have checked.
This is what is given in Dio docs:
For downloading a file:
response = await dio.download('https://www.google.com/', './xx.html');
But here we cannot add request body or headers.
Also I need to download the file to a specific folder in the device such as /downloads folder in internal storage.
When download is successful, we can open the file right from that screen.
How to proceed? I am very new to Flutter.
You can use options parameter. You also can add cookie or other parameters.
response = await dio.download(
'https://www.google.com/', './xx.html',
options: Options(
headers: {'cookie': 'any_cookie'},
method: 'POST',
),
);

Flutter Dio package Exception 413 when uploading an image

I am trying to upload a jpg image using Form data through the Dio package, the request is working properly on Postman, so i think the problem is either in my code or in the image am trying to upload.
As for the image, I have a bitmap with some edits applied on it, i turn this btm into a Uint8List and then I encode it into a jpg file, i use the Bitmap plugin to do that.
final directory = await getApplicationDocumentsDirectory();
File image = await File('${directory.path}/image.jpg').create();
await image.writeAsBytes(widget.editedBitmap.buildHeaded());
Then i get the image width and height through decoding it
var decodedImage = await decodeImageFromList(imageBytes);
print(decodedImage.width);
print(decodedImage.height);
and then i create my form data
FormData formData = new FormData.fromMap({
'title': titleController.text,
'description': descriptionController.text,
'is_public': privacy == 'Public' ? true : false,
'photo_width': decodedImage.width,
'photo_height': decodedImage.height,
'media_file': await MultipartFile.fromFile(
image.path,
filename: image.path.split("/").last,
contentType: new MediaType("image", "jpeg"),
),
});
then i create my dio instance and configure the options
var dio = new Dio();
dio.options.baseUrl = globals.HttpSingleton().getBaseUrl();
dio.options.connectTimeout = 5000; //5s
dio.options.receiveTimeout = 3000;
dio.options.headers = {
HttpHeaders.acceptHeader: '*/*',
HttpHeaders.authorizationHeader: 'Bearer ' + globals.accessToken,
HttpHeaders.contentTypeHeader: 'multipart/form-data'
};
and here is my request
Response response;
try {
response = await dio.post(
'/photos/upload',
data: formData,
onSendProgress: (int sent, int total) {
print('$sent $total');
},
);
} on DioError catch (e) {
print(e.response.data);
}
And here is the response (e) i get
I/flutter (12154): <html>
I/flutter (12154): <head><title>413 Request Entity Too Large</title></head>
I/flutter (12154): <body>
I/flutter (12154): <center><h1>413 Request Entity Too Large</h1></center>
I/flutter (12154): <hr><center>nginx/1.18.0 (Ubuntu)</center>
I/flutter (12154): </body>
I/flutter (12154): </html>
when I searched about this, it said that 413 happens when my request is too large for the server, however, using postman, and while uploading a bigger sized image, it still works which doesn't make sense to me, any idea what could be the problem?
If any further info is needed please let me know.
Turns out when the server was deployed, if not specified, the upload limit is set to 1MB by default, and due to my mistake of uploading different images with different sizes from phone and postman, it took me a lot of time to figure it out. I contacted the DevOps and it was solved.

flutter how to upload file with content type in dio

hello i try to upload image with dio package but i have to set contentType for image but i can not set it and get this error when set MediaType ====> The method 'MediaType' isn't defined for the type 'AnalyzeData'.
this is mycode
Dio dio = new Dio();
dio.options.headers = {
'token': token,
};
try {
String ip = await getServerIP();
FormData formData = new FormData.fromMap({
"front":front==null?null: MultipartFile.fromFileSync(
front,
filename: "image.png",
contentType: MediaType() <=== get error in this line
),
}
);
response = await dio.post("$url", data: formData);
how can i fix it
i use last version of Dio package
you should define contentType like this with type and subtype:
contentType: MediaType(type,subType)
// example MediaType('image','png')
Also be careful about MediaType it comes from diffrent libraries so you should use package http_parser to use it...
Just Add lib http_parser to use MediaType() with Dio
import the given package
import 'package:http_parser/http_parser.dart';
it has worked for me

Flutter dio image upload not working throws server 500 error, but works in postman

This is my postman request with a header auth token.
I am trying to upload image everything is set up as mentioned with dio docs and exactly the same as postman parameter but 500 error is thrown, could not find any mistake here. been stuck here like for 3 hours.
please find any mistake here i am stuck here thanks! (ps: postaman file takes only image file i.e jpg, png other file excluding images will also throw same as 500 error like app is throwing)
and my dio request is:
Future requestChangePhoto(
String wardenToken, String wardenId, File imageFile) async {
String fileName = imageFile.path.split('/').last;
print(fileName);
print(getWardenPhotoChange);
FormData data = FormData.fromMap({
"wardenId": "${wardenId.trim()}",
"photo": await MultipartFile.fromFile(imageFile.path,
filename: fileName, contentType: MediaType("image", "jpg")),
});
Dio dio = new Dio();
dio.options.headers['content-Type'] = 'application/json';
dio.options.headers["authorization"] = "$wardenToken";
await dio
.post("$getWardenPhotoChange", data: data)
.then((response) => print(response.data));
}
This is my ImagePicker and request:
var imageFile = await ImagePicker.pickImage(source: imageType == ImageType.camera? ImageSource.camera: ImageSource.gallery,
imageQuality: 50, maxHeight: 500, maxWidth: 500
);
print(imageFile);
NetworkHandler networkHandler = NetworkHandler();
networkHandler.requestChangePhoto(xybaData.WardenToken, xybaData.wardernId, imageFile);
This is my error:
Since the latest updates, content-type is not treated by Dio as a "normal" header. What I mean is that it ignores that header.
To make it work, set the dio.options.contentType property instead.
Wrapping it up, instead of this:
dio.options.headers['content-Type'] = 'application/json';
try this:
dio.options.contentType = 'application/json';
Bonus:
When creating a Dio instance, you can pass a BaseOptions to its constructor like this:
Dio dio = Dio(
BaseOptions(
headers: {"authorization": wardenToken},
contentType = "application/json",
)
);
I believe its a cleaner way of doing things :D