Got invalid request body when try to upload data through S3 presigned url in flutter - flutter

I am trying to upload an image using resigned URL .But I got
Invalid argument(s): Invalid request body "[object File]".I tried with text also.
I think issue is due to content type.But I don't know what content type is give for "Object File".
Future<void> uploadfile(String url, File image, String type) async {
var urls = Uri.parse(url);
try {
try{
var response = await http.put(
urls,
body:image,
headers: {
"Content-Type":"image/$type",
},
);
print("respons is ${response.statusCode}");
}catch(e){
print("catch error is $e");
}
} catch (e) {
throw ('Error uploading photo');
}
}

This is my function that i create it for update image, use this:
and Uint8List is my type of image_file
var request = http.MultipartRequest("put", uri);
var image = http.MultipartFile.fromBytes(
'image',
image_file,
filename: 'image.jpg',
);
request.files.add(image);
request.fields.addAll(body as Map<String, String>);
request.headers.addAll(headers!);
response = await http.Response.fromStream(await request.send());

Related

How to upload image to server in flutter

How does uploading image to server works in flutter! The ImagePicker return a path to directory,what url should be sent to server and what url should be used to show image on app if I want to upload a png format with autorization token in form-data with key profile_image and to show the similar Image.Below is one of the multiple I tried..
asyncFileUpload(File file) async {
var request = http.MultipartRequest(
"POST",
_getUri(
'/profilepicture',
));
var token = getHeaders();
request.headers["authorization"] = token as String;
;
var pic = await http.MultipartFile.fromPath("profile_image", file.path);
request.files.add(pic);
var response = await request.send();
var responseData = await response.stream.toBytes();
var responseString = String.fromCharCodes(responseData);
print(responseString);
}
What you are sending to the server is .png file and what is supposed to be shown to the user is the image in the server(url path) not the url path from phone. Therefore if the response returns that url all you need to do is get hold of it in the NetworkImage('url') or Image.network('url')
Note: It would be easy if you first show the picked image in your view then have a button that does the submit to the server. If successful replace the image picked url with the url from the server
asyncFileUpload(File file) async {
try {
var request = http.MultipartRequest(
'POST',Uri.parse('url'));
var token = getHeaders();
request.headers["authorization"] = token as String;
request.headers.addAll({
'Content-Type': 'application/json'
});
//request.fields.addAll({
// 'user_id': userId,
//});
request.files.add(await http.MultipartFile.fromPath('profile_image',file.path));
var response = await request.send();
var serverResponse = await http.Response.fromStream(response);
final responseData = json.decode(serverResponse.body);
if(response.statusCode == 200 || response.statusCode == 201){
return responseData;
}else{
return responseData;
}
} catch (e) {
print("Error occurred: $e");
return Future.error(e);
}
}

How to pass header to URL in Flutter

I have a question regarding how to view a PDF from URL.
I’m using flutter_pdfview library and I try to get a PDF from an URL and to view it in my Flutter app.
The problem is that my URL can be accessed ONLY with a token (session ID/header), but I don’t know how to pass it because is not working on the way I do it at the moment.
Here is an example of how the owner of the flutter_pdfview library is getting the PDF from an URL (without a Header): https://github.com/endigo/flutter_pdfview/blob/master/example/lib/main.dart#L49
And here is my code where I don’t know how else to pass the header than like this:
Future<File> createFileOfPdfUrl() async {
Completer<File> completer = Completer();
if (kDebugMode) {
print("Start download file from internet!");
}
try {
String url =
"$customURL.pdf";
if (kDebugMode) {
print("url: $url");
}
final filename = url.substring(url.lastIndexOf("/") + 1);
var client = HttpClient();
HttpClientRequest request = await client.getUrl(Uri.parse(url));
request.headers.add(
HttpHeaders.acceptHeader,
HeaderValue(
"text/plain", {'APPAUTH': '${widget.authService.loginToken}'})); // this method doesn't seems to work for me. I'm getting an empty PDF.
var response = await request.close();
var bytes = await consolidateHttpClientResponseBytes(response);
var dir = await getApplicationDocumentsDirectory();
if (kDebugMode) {
print("Download files");
print("${dir.path}/$filename");
}
File file = File("${dir.path}/$filename");
await file.writeAsBytes(bytes, flush: true);
completer.complete(file);
} catch (e) {
throw Exception('Error parsing asset file!');
}
return completer.future;
}
DO NOT do this:
request.headers.add(
HttpHeaders.acceptHeader, // here is the problem
HeaderValue(
"text/plain", {'APPAUTH': '${widget.authService.loginToken}'}));
SOLUTION for me:
request.headers.add("APPAUTH", "12345abcde67890defgh");
For some reason if you provide a HeaderValue you also need to provide a string value before it, which can be HttpHeaders.acceptHeader or HttpHeaders.serverHeader etc. I tried a lot of them from that enum list and none worked for me so I used the above solution where you don't need to pass that HttpHeader value type.

DioError (DioError [DioErrorType.other]: Bad state: Can't finalize a finalized MultipartFile

I am attempting to upload multiple files using Dio, upon the request being sent I am receiving the error:
DioError (DioError [DioErrorType.other]: Bad state: Can't finalize a finalized MultipartFile.
My request is as follows:
Future<String> sendRequest() async {
_className = classController.text;
_studentName = studentController.text;
_assnNum = assignmentController.text;
if (_className != null && _studentName != null && _assnNum != null) {
var url =
"http://157.245.141.117:8000/uploadfile?collection=$_className&assn_num=$_assnNum&student_name=$_studentName";
var uri = Uri.parse(url);
var formData = FormData();
for (var file in _files) {
print('FilePath: ${file.path}');
formData.files.addAll([
MapEntry("assignment", await MultipartFile.fromFile(file.path)),
]);
var response = await dio.post(
url,
data: formData,
options: Options(headers: {
HttpHeaders.contentTypeHeader: "application/x-www-form-urlencoded",
}),
);
print(response.statusCode);
}
}
return '';
}
I am receiving a status on my api of 200, all params are being passed, but the files are not being uploaded. I'm not sure where to begin. I am uploading cpp files and python files, most examples I have found are dealing exclusively with images. I am unsure how to proceed.

Flutter Http Multi part Request get response body

I want to get response data from MultipartRequest
I uploaded an image to service and I should get image URL in response but I got an Bad state: Stream has already been listened to.
this My code snippet
//upload image
Future<ApiResponse> uploadOrderPic(
{required String orderID,
required File image,
required String type}) async {
ApiResponse apiResponse = ApiResponse();
var token = await getToken();
try {
var request = http.MultipartRequest(
"POST", Uri.parse(uploadPicUrl));
request.files
.add(await http.MultipartFile.fromPath('image', image.path));
request.fields['id'] = '1084';
request.fields['type'] = 'invoice';
request.headers['${HttpHeaders.authorizationHeader}'] = 'Bearer $token';
request.send().then((value) => http.Response.fromStream(value).then((onValue) {
try {
// get response...
logger.i(value.stream.bytesToString());
} catch (e) {
// handle exception
logger.e(e);// This catch Stream has already been listened to.
}
}));
} catch (e) {
logger.e(e);
apiResponse.error = serverError;
}
return apiResponse;
}
the logger.i(value.statusCode); print status code is 200(ok)
but
logger.i(value.stream.bytesToString()); print exception

Upload image to Azure blob using Flutter (iOS/Android)

How can we upload images(.jpg, .png) to Azure blob storage. Not getting any insight to start with.
If you have used example would love to see and try if that is the way to do, any working example/url would help get started with
Here is i am trying to upload .jpg file and getting 400 error,
image.forEach((element) async {
ImageDetailsUpload result = ImageDetailsUpload.fromJson(element);
var postUri = Uri.parse('$url/${result.fileName}?$code'); //Azure blob url
var request = new http.MultipartRequest("PUT", postUri); //Put method
request.files.add(
new http.MultipartFile.fromBytes(
'file',
await File.fromUri(Uri.parse(result.path)).readAsBytes(),
),
);
request.send().then((response) {
print(response.statusCode);
}, onError: (err) {
print(err);
});
});
image is a LIST and holds the fileName and File path, this is what i get as bytes (see image below)
Solved the issue of upload but image is being corrupted now on server -
image.forEach((element) async {
ImageDetailsUpload result = ImageDetailsUpload.fromJson(element);
var postUri = Uri.parse('$url/${result.fileName}?$code');
var request = new http.MultipartRequest("PUT", postUri);
request.headers['X-MS-BLOB-TYPE'] = 'BlockBlob';
request.files.add(
new http.MultipartFile.fromBytes(
'file',
await File.fromUri(Uri.parse(result.path)).readAsBytes(),
),
);
request.send().then((response) {
print(response.statusCode);
}, onError: (err) {
print(err);
});
});
this seems to haunting me.
There is more to the question, what i noticed is the file uploaded using postman to blob storage are store as actual image of type image/jpeg depending on what type of image i am uploading. But when uploading using application i am using as mutipart which is making th e stored file into of type multipart/form-data. Uploaded both types of image jpg/png both gives type as mentioned above.
[![enter image description here][3]][3]
check here if you are using HTTP
How to upload images and file to a server in Flutter?
check this code if you are using Dio
FormData formData = FormData.from({
"name": "wendux",
"age": 25,
"file": await MultipartFile.fromFile("./text.txt",filename: "upload.txt")
});
response = await dio.post("/info", data: formData);
and check Dio's documentation
https://pub.dev/packages/dio
Here is a working example from one of my codes
Future<UploadImageResultModel> uploadImage(File image, String memberToken,
{String type = "IMAGE"}) async {
var uri = Uri.parse('${Constants.baseUrl}member/UploadImage/$type');
var request = new http.MultipartRequest("POST", uri);
request.headers.addAll({
"Authentication": memberToken,
});
var stream = new http.ByteStream(DelegatingStream.typed(image.openRead()));
var length = await image.length();
var multipartFile = new http.MultipartFile('file', stream, length,
filename: image.path.split("/").last);
request.files.add(multipartFile);
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
if (response.statusCode != 200)
return UploadImageResultModel.fromJson(json.decode("{}"));
return UploadImageResultModel.fromJson(json.decode(response.body));
}
First, convert the image File to Stream as data will be a push to the blob container in form of a stream.
Future uploadImage(File file) async {
String fileName = file.path.split('/').last;
_logger.info("File Path: " + fileName);
String imageToken = "Get your own token";
String containerName = "Blob container name";
final fileBytes = file.readAsBytesSync();
var streamData = Stream.fromIterable(fileBytes.map((e) => [e]));
String uploadDestinationUrl = RollaConstants.HOST_IMAGE +
"/$containerName" +
"/$fileName" +
imageToken;
final Dio _dio = Dio();
Response response;
try {
response = await _dio.put(uploadDestinationUrl,
data: streamData,
options: Options(headers: {
Headers.contentLengthHeader: fileBytes.length,
"x-ms-blob-type": "BlockBlob",
"content-type": "image/jpeg"
}));
} catch (error, stacktrace) {
print("Exception occured: $error.response stackTrace: $stacktrace");
}
print("Blob response: " + response.statusCode.toString());
}