Returning a value from a response stream inside an upload function - flutter

I've created a function which uploads an imageFile to Node.js server & AWS Bucket
If I call response.stream.transform(utf8.decoder).listen((value) async {} the value is equal to the CloudFront URL where my picture is stored
I'm trying to extract this URL from my Upload function to use it in my app but I can't find how :
Future<String> upload(File imageFile) async {
String url = '';
[...] // some code
// add file to multipart
request.files.add(multipartFile);
// send
var response = await request.send();
// listen for response
response.stream.transform(utf8.decoder).listen((value) async {
print(value); // prints the URL
url = value; // this value is the url where my picture is stored
// I'd like to use it outside this function
// I thought of returning it but I get an empty string
});
return url;
}

response.stream is a ByteStream. Rather than calling listen, call bytesToString - details here.
So you replace the whole transform section with:
return await response.stream.bytesToString();

Related

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.

Send header in HTTP post request in flutter

first of all i have LoginPageModel to run HTTP post request like this
class LoginPageModel {
String CODD_VALU;
String CODD_DESC;
LoginPageModel({required this.CODD_VALU, required this.CODD_DESC});
static Future<LoginPageModel> connect(String CODD_VALU) async {
Uri url = Uri.parse("http://deltaprima.rmdoo.com/api/office/all");
var response = await http.post(
url,
headers: {
"CompanyCode": "MW",
},
);
var dataJson = jsonDecode(response.body);
debugPrint(dataJson);
return LoginPageModel(
CODD_VALU: dataJson["CODD_VALU"],
CODD_DESC: dataJson["CODD_DESC"],
);
}
}
Then i run LoginPageModel on initState class. Like this
void initState() {
super.initState();
LoginPageModel.connect("MW").then((value) {
print(value);
});
}
But i cant get the Print of the value on my debugConsole, and the "CompanyCode" must send trough headers. im also trying postman, it worked and get the data from api like this.
[
{
"CODD_DESC": "DELTA PRIMA",
"CODD_VALU": "01"
}
]
But i cant get data from API using my flutter app. How
If using post is not strictly necessary, you can use get instead.
String url ='http://deltaprima.rmdoo.com/api/office/all';
var response = await http.get(Uri.parse(url),
headers: {
"CompanyCode": "MW",
});
Moreover, please check if you're using get or post method in postman.

How to convert multiPartRequest's response into normal http response in flutter?

I have to send api request to upload a file to the server.
the pattern:
repo,
provider
service
i have followed fails because of the response multipartRequest sends
how can i convert the request got into normal get/post request ?
Future mutliPartPostRequest(
{required String method,
required String url,
Map<String, String>? headers,
File? file,
String? document,
Map? data}) async {
Map<String, dynamic> jsonResponse;
try {
var request = http.MultipartRequest(method, Uri.parse(url));
data!.forEach((key, value) {
request.fields[key] = value.toString();
});
request.headers['Authorization'] = headers!['authorization']!;
/// [FILTERING] : the null image if there are no photos in the request it will skip adding the photo in the request
if (file != null) {
var picture = await http.MultipartFile.fromPath("photo", file.path);
request.files.add(picture); //adds the photo to the request
}
// Checking the document if it is empty, if it is empty it will skip to add the document in the request
if (document != null) {
var doc = await http.MultipartFile.fromPath('document', document);
request.files.add(doc); // adds the document to the request
}
///Our case starts from this line, while sending multipart request, the response we get is quite different than the normal json data response.
// response => stores the response got
var response = await request.send().timeout(const Duration(seconds: 10)); //sends the request body to the server
// result => coverts the multipart response got from the server to the normal request
var result = await http.Response.fromStream(response);
jsonResponse = returnResponse(result); /// returns the response according to the status code from [returnResponse] function
} on SocketException {
throw FetchDataException({"detail": "No Internet Connection"});
}
return jsonResponse;
}

How to use Uri function properly in Flutter? Difference between Uri and Url

I am confused with the URL and Uri in dart/flutter.
I created this function to be used in my PDF viewer.
static Future<File> loadNetwork(String url) async {
final response = await http.get(Uri.parse(url));
final bytes = response.bodyBytes;
return _storeFile(url, bytes);
}
and I want to call this function to display the specific PDF after clicking a button.
onTap: () async {
setState(() {
isLoading = true;
});
final url = 'http://www.africau.edu/images/default/sample.pdf';
final file = await PDFApi.loadNetwork(url);
openPDF(context, file);
setState(() {
isLoading = false;
});
},
But, still, how do I properly use the Uri and fetch the pdf link. There is an error and I suspect I am using the function wrongly.
It says invalid internet address.
Thanks!
To convert a url to Uri use Uri.parse("url here")

Flutter: display text from HTTP response

I have a link.txt file that i want to display it's content on a text widget
I tried this approach
try {
HttpClient client = HttpClient();
client.getUrl(Uri.parse(arbitaryLink.txt)).then((HttpClientRequest request) {
return request.close();
}).then((HttpClientResponse response) {
response
.transform(Utf8Decoder())
.listen((contents) {
// Do something here with contents
return Text(contents);
});
});
} catch (exception) {
print(exception);
}
contents is the response text .. whenever i try using it outside of it's scope, i get null value.
i tried returning Text, i even tried assigning it to a static variable but i got nothing.
Soo.. What am i doing wrong?
This is how i solved
Future<String> _fetchBtaqa() async {
final response = await http.get('https://www.albetaqa.site/social/data/alwaraqa/02quran/1quran03/p-quran116.txt');
if (response.statusCode == 200) {
var decoded = utf8.decode(response.bodyBytes);
print(decoded);
return decoded;
} else {
return "Error";
}
}
If by outside its scope you mean that you are returning the value of the response and then trying to use it in some widget, then the case might be that you are not waiting for the client to fetch the response.
1) make sure the when you print contents in the scope you are getting a value
2) put the api call or the networking call in a function and add the await keyword to wait for the response.
3) When the response succeeds you can call setState to rebuild the widget with the new value of contents