I have a flutter application that select and upload audio file to server with asp.net rest api.
my flutter code as follows
uploadFile() async {
print(file.path);
var postUri = Uri.parse("http://192.168.1.100:5041/api/fileup/up");
var request = new http.MultipartRequest("POST", postUri);
request.fields['user'] = 'blah';
request.files.add(new http.MultipartFile.fromBytes('file', await File.fromUri(Uri.parse(file.path)).readAsBytes(),contentType: MediaType('audio','mp3')
));
request.send().then((response) {
if (response.statusCode == 200) {
print("Uploaded!");
}else{
print(response.reasonPhrase);
}
});
}
my file.path value for above flutter code is "/data/user/0/com.mydomain.myappname/cache/file_picker/Over_the_Horizon.mp3" which is returned from file picker.
I am able to upload file with postman, but flutter code gives me 500: Internal Server Error
Postman Screenshot
tried with several codes found on stack overflow , all gave me same error
Did you tried with DIO?
You can accomplish this with DIO, like this:
FormData formData = new FormData.fromMap({
"file": await MultipartFile.fromFile(file.path,
filename: file.path.split('/').last)
});
await dio.post('http://192.168.1.100:5041/api/fileup/up', data: formData, onSendProgress: (int begin, int end) {
var initial = begin;
var done = end;
print('$initial $end');
});
Related
I am trying using file_picker and dio packages to upload files as form data.
This is for flutter web and it seems MultipartFile.fromFile is not accepted.
What I tried is the following:
if (result != null) {
for (var file in result.files) {
final formData = FormData.fromMap({
...someOtherData,
'file': File(file.name), // <------ I guess this is where the issue is, I also tried file instead of File(file.name)
});
dio.post(
url,
data: formData,
);
}
}
Ok, I found it, leaving here for someone having the same problem
if (result != null) {
for (var file in result.files) {
final formData = FormData.fromMap({
...someOtherData,
'file': MultipartFile.fromBytes(file.bytes as List<int>)
});
dio.post(
url,
data: formData,
);
}
}
If anyone is still wondering how to get it working on both mobile and web (This is using the image_picker's PickedFile as the image variable type) :
FormData body;
final bytes = await image.readAsBytes();
final MultipartFile file = MultipartFile.fromBytes(bytes, filename: "picture");
MapEntry<String, MultipartFile> imageEntry = MapEntry("image", file);
body.files.add(imageEntry);
**
The catch is that the filename is required on web and is automatically assigned on mobile.**
I am stuck in issue with upload large file. A flutter application compiled for Web and App (Native) when file upload from app is working fine but web it hanged. how to send large file as stream request.
I am new in flutter and working on current existing app which has a feature to upload large tutorial video files and PDF files. requirement is to show the progress bar during the upload the file, currently app has I used dio but it hanged in web version and not file not upload operation going failed.
File size approximate 400MB to 700MB
Currently using following packages
dependencies:
http: ^0.12.2
dio: ^3.0.10
Could you please help me out for this issue?
I am trying to achieve with below code but some how it not working.
https://github.com/salk52/Flutter-File-Upload-Download
It's thrown an error like "Memory buffer allocation failed ", I am unable to update the version of dio or http due to other package goes disturb. somehow I have to achieve it using httpclient or dio. I could not update the version for package because it messed up other package dependency.
Sample ref. code as below:
File size approximate around 500 MB to 700MB
For ref. following code which using in code.
Dio package example:
#Dio example start
Future<NormalResponse> addSubjectMaterial(
{GetSubjectMaterial objSubMat,
bool isDelete,
PlatformFile objfile,
Function sendProgress,
Function receiveProgress,
dio.CancelToken cancelToken}) async {
NormalResponse objRes = NormalResponse();
try {
print(objSubMat.objMaterial.subjectId);
dio.FormData formData = dio.FormData();
formData.fields.add(MapEntry("ObjSubMat", json.encode(objSubMat)));
formData.fields.add(MapEntry("IsDelete", isDelete.toString()));
formData.fields
.add(MapEntry("ClassesId", AppConstants.classesId().toString()));
if (objfile != null) {
formData.files.add(
MapEntry("objfile", await getMultipartFile(objfile, "objfile")));
}
var resp = await dio.Dio().post(
AppConstants.addUpdateSubjectMaterial,
data: formData,
options: requestConfig,
cancelToken: cancelToken,
onSendProgress: sendProgress,
onReceiveProgress: receiveProgress,
);
// String respStr = resp.toString();
// objRes = NormalResponse.fromJson(json.decode(respStr));
objRes = NormalResponse.fromJson(resp.data);
} catch (err) {
objRes.err = err.toString();
objRes.isSuccess = false;
objRes.newId = -1;
sendProgress = null;
receiveProgress = null;
}
return objRes;
}
#Dio example end
#httpclient example code is there any solution with progress bar in this sample code.
Future<NormalResponse> addUpdateSubjectMaterialHttp(
{GetSubjectMaterial objSubMat,
bool isDelete,
PlatformFile objfile,
Function sendProgress,
Function receiveProgress,
dio.CancelToken cancelToken}) async {
NormalResponse objRes = NormalResponse();
try {
var req = http.MultipartRequest(
"POST",
Uri.parse(AppConstants.addUpdateSubjectMaterial),
);
req.headers.addAll({
'Content-type': 'application/json',
'Accept': 'application/json',
});
req.fields['ObjSubMat'] = json.encode(objSubMat);
req.fields['IsDelete'] = isDelete.toString();
req.fields['ClassesId'] = AppConstants.classesId().toString();
if (objfile != null) {
req.files.add(http.MultipartFile(
"objFile", objfile.readStream, objfile.size,
filename: objfile.name));
}
var resp = await req.send();
String result = await resp.stream.bytesToString();
objRes = NormalResponse.fromJson(json.decode(result));
print(objRes.isSuccess);
print(objRes.err);
print("Here done");
} catch (err) {
print(err);
throw err;
}
return objRes;
}
#httpclient
Http package example:
#example start
Future<NormalResponse> addSubjectMaterial(
{GetSubjectMaterial objSubMat,
bool isDelete,
PlatformFile objfile,
Function sendProgress,
Function receiveProgress,
dio.CancelToken cancelToken}) async {
NormalResponse objRes = NormalResponse();
try {
print(objSubMat.objMaterial.subjectId);
dio.FormData formData = dio.FormData();
formData.fields.add(MapEntry("ObjSubMat", json.encode(objSubMat)));
formData.fields.add(MapEntry("IsDelete", isDelete.toString()));
formData.fields
.add(MapEntry("ClassesId", AppConstants.classesId().toString()));
if (objfile != null) {
formData.files.add(
MapEntry("objfile", await getMultipartFile(objfile, "objfile")));
}
var resp = await dio.Dio().post(
AppConstants.addUpdateSubjectMaterial,
data: formData,
options: requestConfig,
cancelToken: cancelToken,
onSendProgress: sendProgress,
onReceiveProgress: receiveProgress,
);
// String respStr = resp.toString();
// objRes = NormalResponse.fromJson(json.decode(respStr));
objRes = NormalResponse.fromJson(resp.data);
} catch (err) {
objRes.err = err.toString();
objRes.isSuccess = false;
objRes.newId = -1;
sendProgress = null;
receiveProgress = null;
}
return objRes;
}
#example end
You must use Future, await and async which continues the task of streams in background thread while the UI of your application works smoothly.
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());
}
I am trying to Upload Multiple Images through Api but i am not understanding how to send a list, I can upload a single image though. Tried alot of searches but does'nt helped, i also import multi_image_picker i can pick the images but the problem is in uploading.
Future<Map<String, dynamic>> _uploadImage(File image) async {
String value = '';
SharedPreferences pref2 = await SharedPreferences.getInstance();
value = pref2.getString("user_role");
final mimeTypeData =
lookupMimeType(image.path, headerBytes: [0xFF, 0xD8]).split('/');
// Intilize the multipart request
final imageUploadRequest = http.MultipartRequest('POST', apiUrl);
// Attach the file in the request
final file = await http.MultipartFile.fromPath('photo', image.path,
contentType: MediaType(mimeTypeData[0], mimeTypeData[1]));
// Explicitly pass the extension of the image with request body
// Since image_picker has some bugs due which it mixes up
// image extension with file name like this filenamejpge
// Which creates some problem at the server side to manage
// or verify the file extension
imageUploadRequest.files.add(file);
imageUploadRequest.fields['mobile'] = _mobileNo.text;
imageUploadRequest.headers.addAll({
'Content-Type': 'application/json',
'Authorization': Constants.authToken,
});
var response = await imageUploadRequest.send();
if (response.statusCode == 200) print('Done!');
final respStr = await response.stream.bytesToString();
return json.decode(respStr);
}
this an example of uploading files to your API with HTTP package
import 'package:http/http.dart' as http;
void uploadFiles(List<File> files) async {
final url = YOUR-API-LINK;
for (var file in files) {
// Create a multipart request
var request = http.MultipartRequest('POST', Uri.parse(url));
// Add the file to the request
request.files.add(http.MultipartFile.fromBytes(
'file',
file.readAsBytesSync(),
filename: file.path.split('/').last,
));
// Send the request
var response = await request.send();
// Check the status code
if (response.statusCode != 200) {
print('Failed to upload file');
}else{
print response.body;
}
}
}
for Dio use this
void uploadFiles(List<File> files) async {
final url = YOUR-API-LINK;
// Create a Dio client
var dio = Dio();
// Create a FormData object
var formData = FormData();
// Add the files to the FormData object
for (var file in files) {
formData.files.add(MapEntry(
'file',
await MultipartFile.fromFile(file.path, filename: file.path.split('/').last),
));
}
// Send the request
var response = await dio.post(url, data: formData);
// Check the status code
if (response.statusCode != 200) {
print('Failed to upload files');
}else {
print(response.data)
}
}
as you can see there not much difference between them in http you use MultipartRequest in dio you use FormData.
This question already has an answer here:
Upload image with http.post and registration form in Flutter?
(1 answer)
Closed 3 years ago.
I am new to Flutter development. My problem is that I try to upload the image but I keep getting failed request.
This piece of code is where I connect it with a server API which will receive the image file from Flutter. String attachment which consist of the image path that is passed from createIncident function located at another page.
Future<IncidentCreateResponse> createIncident( String requesterName, String requesterEmail,
String requesterMobile, String attachment, String title,
String tags, String body, String teamId,
String address ) async {
IncidentCreateResponse incidentCreateResponse;
var url = GlobalConfig.API_BASE_HANDESK + GlobalConfig.API_INCIDENT_CREATE_TICKETS;
var token = Auth().loginSession.accessToken;
var postBody = new Map<String, dynamic>();
postBody["requester_name"] = requesterName;
postBody["requester_email"] = requesterEmail;
postBody["requester_mobile_no"] = requesterMobile;
postBody["attachment"] = attachment;
postBody["title"] = title;
postBody["tags"] = tags;
postBody["body"] = body;
postBody["teamId"] = teamId;
postBody["address"] = address;
// Await the http get response, then decode the json-formatted responce.
var response = await http.post(
url,
body: postBody,
headers: {
'X-APP-ID': GlobalConfig.APP_ID,
"Accept": "application/json; charset=UTF-8",
// "Content-Type": "application/x-www-form-urlencoded",
HttpHeaders.authorizationHeader: 'Bearer $token',
'token': GlobalConfig.API_INCIDENT_REPORT_TOKEN
}
);
if ((response.statusCode == 200) || (response.statusCode == 201)) {
print(response.body);
var data = json.decode(response.body);
incidentCreateResponse = IncidentCreateResponse.fromJson(data['data']);
} else {
print("createIncident failed with status: ${response.statusCode}.");
incidentCreateResponse = null;
}
return incidentCreateResponse;
}
This is the code snippet where I get the image path from the selected image from the gallery
Future getImageFromGallery(BuildContext context) async {
var picture = await ImagePicker.pickImage(source: ImageSource.gallery);
setState((){
_imageFile = picture;
attachment = basename(_imageFile.path);
});
Navigator.of(context).pop();
}
This is the code where I passed the attachment string to the HTTP Response
this.incidentService.createIncident(
Auth().loginSession.name,
Auth().loginSession.email,
Auth().loginSession.mobile_no,
this.attachment,
this._titleController.text,
this._tags,
this._contentController.text,
this._teamId,
this._addressController.text
).then((IncidentCreateResponse res) {
if (res != null) {
print('Ticket Id: ' + res.id);
// Navigator.pop(context);
this._successSubmittionDialog(context);
} else {
this._errorSubmittionDialog(context);
}
}
You can upload image using multipart or base64 Encode.
For uploading image using multipart Visit the Official documentation
For uploading image using base64 Encode you can checkout the Tutorial Here
I suggest using multipart image upload as it is even reliable when your image or files are larger in size.
Hope this could help you,
create a function to upload your image after picking or clicking an image like,
Future<ResponseModel> uploadPhoto(
String _token,
File _image,
String _path,
) async {
Dio dio = new Dio();
FormData _formdata = new FormData();
_formdata.add("photo", new UploadFileInfo(_image, _path));
final response = await dio.post(
baseUrl + '/image/upload',
data: _formdata,
options: Options(
method: 'POST',
headers: {
authTokenHeader: _token,
},
responseType: ResponseType.json,
),
);
if (response.statusCode == 200 || response.statusCode == 500) {
return ResponseModel.fromJson(json.decode(response.toString()));
} else {
throw Exception('Failed to upload!');
}
}
then you can use use uploadImage,
uploadImage(_token, _image,_image.uri.toFilePath()).then((ResponseModel response) {
//do something with the response
});
I have used Dio for the task, you can find more detail about dio here
Add this to your package's pubspec.yaml file:
dependencies:
dio: ^3.0.5
Then import it in your Dart code, you can use:
import 'package:dio/dio.dart';
To upload image using multipart API use this code ie
Add this library dio in your project in pubspec.yaml file
dio: ^3.0.5
and import this in your class
import 'package:dio/dio.dart';
Declare this variable in your class like State<CustomClass>
static var uri = "BASE_URL_HERE";
static BaseOptions options = BaseOptions(
baseUrl: uri,
responseType: ResponseType.plain,
connectTimeout: 30000,
receiveTimeout: 30000,
validateStatus: (code) {
if (code >= 200) {
return true;
}
});
static Dio dio = Dio(options);
then use this method to upload file
Future<dynamic> _uploadFile() async {
try {
Options options = Options(
//contentType: ContentType.parse('application/json'), // only for json type api
);
var directory = await getExternalStorageDirectory(); // directory path
final path = await directory.path; // path of the directory
Response response = await dio.post('/update_profile',
data: FormData.from({
"param_key": "value",
"param2_key": "value",
"param3_key": "value",
"profile_pic_param_key": UploadFileInfo(File("$path/pic.jpg"), "pic.jpg"),
}),
options: options);
setState(() {
isLoading = false;
});
if (response.statusCode == 200 || response.statusCode == 201) {
var responseJson = json.decode(response.data);
return responseJson;
} else if (response.statusCode == 401) {
print(' response code 401');
throw Exception("Incorrect Email/Password");
} else
throw Exception('Authentication Error');
} on DioError catch (exception) {
if (exception == null ||
exception.toString().contains('SocketException')) {
throw Exception("Network Error");
} else if (exception.type == DioErrorType.RECEIVE_TIMEOUT ||
exception.type == DioErrorType.CONNECT_TIMEOUT) {
throw Exception(
"Could'nt connect, please ensure you have a stable network.");
} else {
return null;
}
}
}