Im using this api to upload a mp3 file
using this method
Future<void> uploadRecord(String matchId, String filePath) async {
Uri url = Uri.parse(
Urls.baseurl + EndPoints.uploadRecordEndPoint + '${auth.token}');
final request = http.MultipartRequest('POST', url)
..fields['match_id'] = matchId
..files.add(http.MultipartFile.fromBytes(
'file', await File.fromUri(Uri(path: filePath)).readAsBytes(),
contentType: MediaType('audio', 'mpeg')));
final response = await request.send();
final responseStr = await response.stream.bytesToString();
print(responseStr);
}
but it doesn't work, it seems that no file uploading, am i missing something ? or is there any better solution ?
Please use flutter_upload package for uploading file
Or use below code for uploading the file using multipart :
static Future<String> fileUploadMultipart(
{File file, OnUploadProgressCallback onUploadProgress}) async {
assert(file != null);
final url = '$baseUrl/api/file';
final httpClient = getHttpClient();
final request = await httpClient.postUrl(Uri.parse(url));
int byteCount = 0;
var multipart = await http.MultipartFile.fromPath(fileUtil.basename(file.path), file.path);
// final fileStreamFile = file.openRead();
// var multipart = MultipartFile("file", fileStreamFile, file.lengthSync(),
// filename: fileUtil.basename(file.path));
var requestMultipart = http.MultipartRequest("", Uri.parse("uri"));
requestMultipart.files.add(multipart);
var msStream = requestMultipart.finalize();
var totalByteLength = requestMultipart.contentLength;
request.contentLength = totalByteLength;
request.headers.set(
HttpHeaders.contentTypeHeader, requestMultipart.headers[HttpHeaders.contentTypeHeader]);
Stream<List<int>> streamUpload = msStream.transform(
new StreamTransformer.fromHandlers(
handleData: (data, sink) {
sink.add(data);
byteCount += data.length;
if (onUploadProgress != null) {
onUploadProgress(byteCount, totalByteLength);
// CALL STATUS CALLBACK;
}
},
handleError: (error, stack, sink) {
throw error;
},
handleDone: (sink) {
sink.close();
// UPLOAD DONE;
},
),
);
await request.addStream(streamUpload);
final httpResponse = await request.close();
//
var statusCode = httpResponse.statusCode;
if (statusCode ~/ 100 != 2) {
throw Exception('Error uploading file, Status code: ${httpResponse.statusCode}');
} else {
return await readResponseAsString(httpResponse);
}
}
Try to add filename to the
http.MultipartFile.fromBytes()
Related
I am working on a flutter project in which user is supposed to create some scripts and by typing them in text and then flutter_tts library is supposed to convert them to audio file which works fine for that time being but I want to save that file into firebase storage for later user. I have tried the following code but it just saves blank audio file in the firebase storage. Any kind of help will be appreciated.
The code I have tried is:
final FlutterTts _flutterTts = FlutterTts();
late var fileName;
/// creation of audio script
Future createAudioScript(
String name,
String script,
String firebasepath,
) async {
await _flutterTts.setLanguage("en-US");
await _flutterTts.setSpeechRate(1.0);
await _flutterTts.setVolume(1.0);
await _flutterTts.setPitch(1.0);
await _flutterTts.setVoice(
{"name": "en-us-x-tpf-local", "locale": "en-US"},
);
await _flutterTts.speak(script);
fileName = GetPlatform.isAndroid ? '$name.wav' : '$name.caf';
print('FileName: $fileName');
var directoryPath =
"${(await getApplicationDocumentsDirectory()).path}/audio/";
var directory = Directory(directoryPath);
if (!await directory.exists()) {
await directory.create();
print('[INFO] Created the directory');
}
var path =
"${(await getApplicationDocumentsDirectory()).path}/audio/$fileName";
print('[INFO] path: $path');
var file = File(path);
if (!await file.exists()) {
await file.create();
print('[INFO] Created the file');
}
await _flutterTts.synthesizeToFile(script, fileName).then((value) async {
if (value == 1) {
print('generated');
var file = File(
'/storage/emulated/0/Android/data/com.solution.thriving/files/$fileName',
);
print(file);
moveFile(file, path, '$firebasepath/$fileName').then((value) {
print('move file: $value');
_app.link.value = value;
print('link: ${_app.link.value}');
});
}
});
}
/// move file from temporary to local storage and save to firebase
Future<String> moveFile(
File sourceFile,
String newPath,
String firebasePath,
) async {
String audioLink = '';
print('moved');
await sourceFile.copy(newPath).then((value) async {
print('value: $value');
await appStorage.uploadAudio(value, fileName, firebasePath).then((audio) {
print(audio);
audioLink = audio;
return audioLink;
});
}).whenComplete(() async {
customToast(message: 'Audio has been generated successfully.');
});
return audioLink;
}
After spending whole day and with the help of a friend, I finally managed to figure out the issue which was being caused because I was using synthesizeToFile() and speak() functions at the same time, which I managed to resolved the issue by changing my code to the following code snippet.
final FlutterTts _flutterTts = FlutterTts();
late var fileName;
/// converting text to speech
Future createAudioScript(
String name,
String script,
String firebasepath,
) async {
await _flutterTts.setLanguage("en-US");
await _flutterTts.setSpeechRate(1.0);
await _flutterTts.setVolume(1.0);
await _flutterTts.setPitch(1.0);
await _flutterTts.setVoice(
{"name": "en-us-x-tpf-local", "locale": "en-US"},
);
if (GetPlatform.isIOS) _flutterTts.setSharedInstance(true);
// await _flutterTts.speak(script);
fileName = GetPlatform.isAndroid ? '$name.wav' : '$name.caf';
log('FileName: $fileName');
await _flutterTts.synthesizeToFile(script, fileName).then((value) async {
if (value == 1) {
log('Value $value');
log('generated');
}
});
final externalDirectory = await getExternalStorageDirectory();
var path = '${externalDirectory!.path}/$fileName';
log(path);
saveToFirebase(path, fileName, firebasPath: '$firebasepath/$name')
.then((value) => {log('Received Audio Link: $value')});
}
/// saving converted audio file to firebase
Future<String> saveToFirebase(String path, String name,
{required String firebasPath}) async {
final firebaseStorage = FirebaseStorage.instance;
SettableMetadata metadata = SettableMetadata(
contentType: 'audio/mpeg',
customMetadata: <String, String>{
'userid': _app.userid.value,
'name': _app.name.value,
'filename': name,
},
);
var snapshot = await firebaseStorage
.ref()
.child(firebasPath)
.putFile(File(path), metadata);
var downloadUrl = await snapshot.ref.getDownloadURL();
print(downloadUrl + " saved url");
return downloadUrl;
}
I am trying to make an document scanner app in flutter where whenever a user clicks a button the PDF that is already created should be added to an SQLite database .For uploading a PDF into a SQLite database in flutter we need to convert the file to a binary.But I don't know how to do that please help me.The code for converting a image to a pdf
String _status = "Not created";
File pdfFile;
FileStat _pdfStat;
bool _generating = false;
Future<File> _assetFromBundle(String name) async {
final tempDir = await getApplicationDocumentsDirectory();
final output = File(path.join(tempDir.path, name));
if (!await output.exists()) {
final data = await rootBundle.load('assets/$name');
final buffer = data.buffer;
output.writeAsBytes(
buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
}
return output;
}
Future<void> _createPdf() async {
try {
this.setState(() => _generating = true);
final tempDir = await getApplicationDocumentsDirectory();
final output = File(path.join(tempDir.path, 'example.pdf'));
this.setState(() => _status = 'Preparing images...');
final images = [ff.image];
this.setState(() => _status = 'Generating PDF');
await ImagesToPdf.createPdf(
pages: images
.map(
(file) => PdfPage(
imageFile: file,
compressionQuality: 0.5,
) ,
)
.toList(),
output: output,
);
_pdfStat = await output.stat();
this.setState(() {
pdfFile = output;
_status = 'PDF Generated (${_pdfStat.size ~/ 1024}kb)';
});
} catch (e) {
this.setState(() => _status = 'Failed to generate pdf: $e".');
} finally {
this.setState(() => _generating = false);
}
}
Future<void> _openPdf() async {
if (pdfFile != null) {
try {
final bytes = await pdfFile.readAsBytes();
await Printing.sharePdf(
bytes: bytes, filename: path.basename(pdfFile.path));
} catch (e) {
_status = 'Failed to open pdf: $e".';
}
}
}
I guess what you are looking for is bytes, use File class to read as bytes,
var f = File('file/path.pdf');
List<int> binaries = await f.readAsBytes();
use the bytes as is or by encoding it to Base64 String
var asString = Base64Codec().encode(binaries);
I get an image by image picker and I am also displying it in future file.
The issue that I hava that i cant send it by URL.
the parameter
Future<File> _profliePicture;
The image picker:
_pickImageFrom(ImageSource imageSource) async {
setState(() {
_profliePicture = ImagePicker.pickImage(source: imageSource);
});
}
My url file sender:
upload(File imageFile) async {
print("starts to upload...");
var stream = new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
var length = await imageFile.length();
var uri = Uri.parse("URL");
var request = new http.MultipartRequest("POST", uri);
var multipartFile = new http.MultipartFile('file', stream, length,
filename: basename(imageFile.path));
//contentType: new MediaType('image', 'png'));
request.files.add(multipartFile);
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}
I'm doing a post request to an ASP.Net Web API to acquire a token. I am able to do this successfully with the dart HTTP package as follow:
Uri address = Uri.parse('https://myaddress:myport/token');
var response = await http.post(
address,
body: {
'username': 'MyUsername',
'password': 'MyPassword',
'grant_type': 'password'
},
).timeout(Duration(seconds: 20));
return response.body;
No problem with Postman either:
Now I want to do the same with the base dart:io class, as the testing server has a self signed certificate which I found the HTTP package has no bypass for (might be wrong), but for the life of me I cannot figure out where I am going wrong as when I debug the server the requests never get hit with the following code:
Uri address = Uri.parse('https://myaddress:myport/token');
HttpClient httpClient = HttpClient();
httpClient.connectionTimeout = Duration(seconds: 20);
httpClient.badCertificateCallback = ((X509Certificate cert, String host, int port) => true); // Allow self signed certificates
HttpClientRequest request = await httpClient.postUrl(address);
final Map<String, String> payLoad = {
'username': 'MyUsername',
'password': 'MyPassword',
'grant_type': 'password'
};
request.headers.contentType = new ContentType("application", "x-www-form-urlencoded", charset: "utf-8");
request.add(utf8.encode(json.encode(payLoad)));
// request.write(payLoad);
HttpClientResponse response = await request.close();
String responseBody = await response.transform(utf8.decoder).join();
httpClient.close();
responseBody is always:
"{"error":"unsupported_grant_type"}"
So I assume my encoding or structure is wrong, but with all possibilities I have tried, nothing works, any help would be appreciated.
i did the same but in my case i am requesting a soap web service, the bellow code do the job for me i hope it will for you
Future<XmlDocument> sendSoapRequest(String dataRequest) async {
final startTime = Stopwatch()..start();
_attemptsRequest = 0;
bool successful = false;
String dataResponse;
try {
Uri uri = Uri.parse('https://address:port/ADService');
var httpClient = HttpClient();
httpClient.connectionTimeout = Duration(milliseconds: 5000);
httpClient.idleTimeout = Duration(milliseconds: 5000);
httpClient.badCertificateCallback = ((X509Certificate cert, String host, int port) => true); // Allow self signed certificates
await httpClient
.openUrl('POST', uri)
.then((HttpClientRequest request) async {
request.headers.contentType =
new ContentType('application', 'text/xml', charset: 'UTF-8');
_attemptsRequest++;
request.write(dataRequest);
await request.close().then((HttpClientResponse response) async {
// var data = await response.transform(utf8.decoder).join();
// i didn't use this method cause it disorganize the response when there is high level of data, -i get binary data from the server-
var data = await utf8.decoder.bind(response).toList();
dataResponse = data.join();
successful = true;
httpClient.close();
});
_timeRequest = startTime.elapsed.inMilliseconds;
});
} catch (e) {
if (_attemptsRequest >= getAttempts) {
_timeRequest = startTime.elapsed.inMilliseconds;
if (e is SocketException)
throw Exception('Timeout exception, operation has expired: $e');
throw Exception('Error sending request: $e');
} else {
sleep(const Duration(milliseconds: 500));
}
}
try {
if (successful) {
XmlDocument doc;
doc = parse(dataResponse);
return doc;
} else {
return null;
}
} catch (e) {
throw Exception('Error converting response to Document: $e');
}
}
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.
Using http package, this is my approach :
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),
);
}
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.
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!
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";});
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
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