getx
getx copied to clipboard
GetConnect stream has already been listened to on multipart use
When using multipart for file upload, the "stream has already been listened to" will be thrown
example:
class ModelProvider extends HttpProvider {
@override
void onInit() {
super.onInit();
}
Future<Response<MyModel>> addImageToModel({
Uint8List? image,
}) {
final formData = FormData({
"image": image == null
? null
: MultipartFile(image, filename: 'image'),
"image2": image == null
? null
: MultipartFile(image, filename: 'image2'),
});
return post('myRoute', formData);
}
}
and this is HttpProvider:
import 'package:get/get.dart';
const API_ENDPOINT = 'http://10.0.2.2:3000/';
class HttpProvider extends GetConnect {
static String? token = "";
SecureStorageController secureStorage = Get.find();
@override
void onInit() {
httpClient.baseUrl = API_ENDPOINT;
httpClient.maxAuthRetries = 2;
httpClient.addAuthenticator<dynamic>((request) async {
final token = await this.secureStorage.getAuthToken();
HttpProvider.token = token;
if (token != null && token != "") {
request.headers['Authorization'] = 'Bearer $token';
}
return request;
});
super.onInit();
}
}
Expected behavior Upload files without errors
Flutter Version: 2.2.3
Getx Version: ^4.3.7
@Ashkan4472 I got same problem with newest version of getx 4.3.8. Did you find the solution ?
this is how i upload multiple images to server using getxConnect
Future
try{
final form=FormData({
'description':description,
});
for(var f in files){
form.files.addAll([
MapEntry('img[]',MultipartFile(f,filename: f.path.split('/').last))
]);
}
var response=await post('/reports',form);
return response.body;
}catch(error){
return Future.error(error.toString());
};
}
I am using version 4.6.1 and still have this problem. I had to switch to the DIO package.
// simplified code
final picker = ImagePicker();
final Rx<XFile?> image = Rx<XFile?>(null);
// Get image after user action
image.value = await picker.pickImage(
source: ImageSource.gallery,
);
// Make a form data body
final _body = {
"image": MultipartFile(await image.value.readAsBytes(), filename: image.value.name),
"notes": "testing",
};
FormData formData = FormData(_body);
// Sending with GetConnect
post("/target-endpoint", formData, contentType: "multipart/form-data");
Just to add my voice, I also have this problem with 4.6.1 (uploading a single file with other form fields). I had to switch to a plain http/http.dart implementation to continue with my project.
Any updates?
I'm facing the same problem... 😕
I hope it can help you or someone else
@LUK3D @andersomdutra @mp035 @roberto-ayala @shelzTimesignature @phamduoc
DON'T USE Content-Type fixed in your headers;
I resolve this removing the Content-Type of the headers, the get make this for you.
My example:
import 'package:path/path.dart' as path;
import 'package:get/get_connect/http/src/multipart/form_data.dart' as fd;
import 'package:get/get_connect/http/src/multipart/multipart_file.dart' as mf;
...
final formData = fd.FormData({
'type': type,
'file1': mf.MultipartFile(pathImgFront,
filename: path.basename(pathImgFront),
contentType: 'multipart/form-data'),
'file2': pathImgVerse == null
? null
: await mf.MultipartFile(pathImgVerse,
filename: path.basename(pathImgVerse),
contentType: 'multipart/form-data')
});
response = await apiRequest.httpClient.post(
'https://your.url/api',
body: formData,
contentType: 'multipart/form-data',
);
In my class that extends WebRequest that extends GetConnect, and i have the request modifier that add my headers
const baseUrl = 'https://yourbaseurl.com'
class APIRequest extends WebRequest implements GetxService {
Future<APIRequest> init() async {
httpClient.baseUrl = baseUrlr;
httpClient.addAuthenticator((Request request) async {
request.headers.addAll(HeadersAPI(token: _fetchToken()).getHeaders());
return request;
});
And in this headers not use Content-Type.
WebRequest
class WebRequest extends GetConnect implements GetxService {
Future<WebRequest> init() async {
httpClient.addRequestModifier((Request request) async {
return request;
});
httpClient.addResponseModifier((request, response) async {
print({
'event': event,
'method': request.method,
'url': request.url.toString(),
'status': response.statusCode
});
return response;
});
return this;
}
}