I've created a flutter application for android and web. In Flutter web, I tried to upload image to server just like it works with firebase. But it is not working somehow. I've seen some solutions for this task. But I wonder, what is actually wrong with my code.
final url = Uri.parse('$apiHeader/poststore');
String token = await getUserToken();
Map<String, String> headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $token'
};
var request = http.MultipartRequest("POST", url);
request.headers.addAll(headers);
request.fields['category_id'] = model.categoryId;
request.fields['title'] = model.title;
//I want to know about this section of the code, how can i make it work
if (kIsWeb) {
final fileBytes =
await model.image.readAsBytes(); // convert into bytes
var multipartFile = http.MultipartFile.fromBytes(
'fileName[]', fileBytes); // add bytes to multipart
request.files.add(multipartFile);
} else {
var multipartFile = await http.MultipartFile.fromPath(
'fileName[]', model.image.path);
request.files.add(multipartFile);
}
var response = await request.send();
Your code seems to be perfect for uploading files to Firebase Storage in flutter web. But it will never work with APIs.
You simply need to change your method of file selection. Instead of image_picker
or file_picker
. You can use the universal_html
package or you could simply import the html.dart
file which comes with flutter
SDK.
First of all import the package
import 'package:universal_html/html.dart' as html;
now use this method to pick the file in web
Future<Either<String, html.File>> pickWebFile() async {
final Completer<Either<String, html.File>> completer = Completer();
html.FileUploadInputElement uploadInput = html.FileUploadInputElement();
uploadInput.accept = '.xlsx, .pdf'; // specify file extensions you want to pick
uploadInput.multiple = false;
uploadInput.click();
uploadInput.onChange.listen((e) {
final files = uploadInput.files;
if (files != null && files.isNotEmpty) {
final file = files.first;
completer.complete(Right(file));
} else {
completer.complete(const Left('No file selected'));
}
});
uploadInput.onError.listen((e) {
completer.complete(const Left('Error selecting file'));
});
return completer.future;
}
once you have picked the file(s), then call this method to to upload file(s) using the API call
Future<Either<String, String>> uploadFileToServer(html.File file) async {
final Completer<Either<String, String>> completer = Completer();
try {
User? user = FirebaseAuth.instance.currentUser;
if (user == null) {
return const Left('User is not logged in');
}
String? token = await user.getIdToken(true);
Uri url = Uri.parse(ApiEndpoints.uploadDoc);
final reader = html.FileReader();
reader.readAsArrayBuffer(file);
reader.onLoadEnd.listen((event) async {
try {
final fileBytes = reader.result as Uint8List;
var request = http.MultipartRequest('POST', url)
..headers['Authorization'] = 'Bearer $token'
..headers['Content-Type'] = 'multipart/form-data'
..files.add(http.MultipartFile.fromBytes('file', fileBytes, filename: file.name));
var response = await request.send();
var responseBody = await http.Response.fromStream(response);
if (response.statusCode == 200) {
debugPrint('File uploaded successfully: ${responseBody.body}');
completer.complete(const Right('File Uploaded Successfully!'));
} else {
debugPrint('Failed to upload file: ${response.statusCode}');
debugPrint('Response: ${responseBody.body}');
completer.complete(Left('Error: ${responseBody.body}'));
}
} catch (e) {
debugPrint('Error uploading file: $e');
completer.complete(Left('Error Uploading File: $e'));
}
});
reader.onError.listen((event) {
debugPrint('Error reading file: ${event.toString()}');
completer.complete(Left('Error: ${event.toString()}'));
});
} catch (e) {
debugPrint('Error uploading file: $e');
completer.complete(Left('Error Uploading File: $e'));
}
return completer.future;
}
please note you need to import these packages to use this code:
import 'dart:convert';
import 'package:dartz/dartz.dart';
import 'dart:io' as io;
import 'package:path/path.dart' as path;
import 'package:intl/intl.dart';
import 'package:http/http.dart' as http;
import 'package:universal_html/html.dart' as html;