Flutter Web Image Picker and Uploading Image to Firebase - flutter

Flutter 2 announced just few days ago and some packages updated for web like Image Picker. I'm trying to get image and upload it to cloud storage. Image picker working very well but when
I want to upload image to storage it gives me error.
Unsupported operation: Platform._operatingSystem
UI Code
onImageSelect: (selectedImage) async {
try {
final url = await Get.find<FirebaseStorageService>()
.uploadProfilePicture(
customer.uuid, File(selectedImage.path));
print(url);
} catch (e) {
print(e);
}
customer.profileImageUrl = selectedImage.path;
_isImageSelected = true;
}),
Service Class funciton:
class FirebaseStorageService {
final FirebaseStorage _firebaseStorage = FirebaseStorage.instance;
Reference _storageReference;
Future<String> uploadProfilePicture(
String userID, File uploadingImagePath) async {
_storageReference = _firebaseStorage
.ref()
.child(userID)
.child('images')
.child("profile-photo.png");
var uploadTask = _storageReference.putFile(uploadingImagePath);
var url = await (await uploadTask).ref.getDownloadURL();
return url;
}
}
I tried flutter clean and flutter upgrade. I also searched old questions and some of them used html.File instead of dart:io library but firebase_storage:7.0.0 package only accept File class which is from dart:io library.
Code work on Android and IOS but not web.
I'm using stable channel.

Related

Get a list of files from the local storage and display it as a list in flutter web:

I've been building an ios app and in it, it'll download a bunch of pdf from an API and save it to the local storage using the path_provider package in flutter:
This is the code I use to fetch the path:
Future<String> get localPath async {
final directory = await getApplicationDocumentsDirectory();
currentDir.value = directory.path;
return directory.path;}
And this is how I save it to the device:
Future<void> saveFilesToLocal(String url, String fileName) async {
try {
final path = await localPath;
final file = File('$path/$fileName');
if (await file.exists() == false) {
final response = await Dio().get(url,
options: Options(
responseType: ResponseType.bytes,
followRedirects: false,
receiveTimeout: 0));
final raf = file.openSync(mode: FileMode.write);
raf.writeFromSync(response.data);
await raf.close();
} else {
print("file already exists");
}
} catch (e) {
print('error: $e');
}
}
After I download and save the files to the storage, it'll be displayed as a gridview in the home page. To fetch that list of files I use this:
List<FileSystemEntity> files = [];
Future<void> getFilesList() async {
files.clear();
final path = await localPath;
Directory dir = Directory('$path');
files =
dir.listSync(recursive: true, followLinks: false);
update();
}
And all of this works fine in the ios device. But the current issue I'm facing while trying to run it on web is:
The package path_provider is not available for flutter web. I've been asked to create it as a web app too and I can't find an alternative for it. While looking for one I saw a post saying flutter web won't allow access to a device's local storage like that so it's not possible. Is it true? Is there a workaround? If it's about security, the app will only be run on specific devices. It won't be given to the public.

Flutter web - Uploading image to firebase storage

I am using the firebase_storage: ^8.0.6 package on flutter web. I want to upload image to firebase storage that I get using FilePicker package.
The problem is that the new package uses the putFile() method to upload files. But File from dart:io doesn't work on flutter web and it also doesn't accept the File object from dart:html.
I can upload image as Blob using the putBlob() method but then it doesn't upload it as image type but it's type is application/octet-stream. I don't want to upload the image file as a blob.
Future<String> uploadImage(PlatformFile file) async {
try {
TaskSnapshot upload = await FirebaseStorage.instance
.ref(
'events/${file.name}-${DateTime.now().toIso8601String()}.${file.extension}')
.putBlob(Blob(file.bytes));
String url = await upload.ref.getDownloadURL();
return url;
} catch (e) {
print('error in uploading image for : ${e.toString()}');
return ';
}
}
How to fix this issue?
You can use the putData() method to send the image and set it's metadata as a image.
Future<String> uploadImage(PlatformFile file) async {
try {
TaskSnapshot upload = await FirebaseStorage.instance
.ref(
'events/${file.path}-${DateTime.now().toIso8601String()}.${file.extension}')
.putData(
file.bytes,
SettableMetadata(contentType: 'image/${file.extension}'),
);
String url = await upload.ref.getDownloadURL();
return url;
} catch (e) {
print('error in uploading image for : ${e.toString()}');
return '';
}
}
putData() method takes Uint8List by default.
Uploading images using TaskSnapshot is not working on my flutter web project.
I used firebase_storage: ^8.1.3 .
Following code is working for my web project.
String nameImage = DateTime.now().millisecondsSinceEpoch.toString();
Reference _reference = FirebaseStorage.instance
.ref()
.child('images/$nameImage.png}');
await _reference
.putData(
await image.readAsBytes(),
SettableMetadata(contentType: 'image/jpeg'),
)
.whenComplete(() async {
await _reference.getDownloadURL().then((value) {
user.profilePictureURL = value;
FireStoreUtils.firestore
.collection(USERS)
.doc(user.userID)
.update({'profilePictureURL': user.profilePictureURL});
});
});
You can still use .putFile when you use the File.fromUri() constructor and get the Uri from the PlatformFile object using Uri.dataFromBytes and passing the bytes to it.
The code below contains changes that should remove the error:
TaskSnapshot upload = await FirebaseStorage.instance
.ref(
'events/${file.name}-${DateTime.now().toIso8601String()}.${file.extension}')
.putFile(File.fromUri(Uri.dataFromBytes(file.bytes.toList())));

Flutter AZURE BLOB IMAGE UPLOAD - How to upload image captured using mobile camera to azure blob storage

I have been working for few since yesterday to try upload an image to azure blob storage taken using mobile camera form iOS/Android device.
I am able to upload the files but for some reason they being corrupted not able to open the image uploaded.
Please check the image error while opening the uploaded image
I am using flutter package http with different approach all work in uploading image file to azure blob store but it gets corrupted somehow , I tried forcing the ContentType to image/jpeg but no help.
Here is code I am using an http API -
takePicture() async {
final pickedFile = await picker.getImage(source: ImageSource.camera);
setState(() {
if (pickedFile != null) {
_image = File(pickedFile.path);
String fileName = basename(pickedFile.path);
uploadFile(fileName, image);
} else {
print('No image selected.');
}
});
}
First approach -->
http.Response response = await http.put(
uri,
headers: {
"Content-Type": 'image/jpeg',
"X-MS-BLOB-TYPE": "BlockBlob",
},
body: image.path,
);
print(response.statusCode);
Using Approach second -->
final data = image.readAsBytesSync();
var dio = Dio();
dio.options.headers['x-ms-blob-type'] = 'BlockBlob';
dio.options.headers['Content-Type'] = 'image/jpeg';
try {
final response = await dio.put(
'$url/$fileName?$token',
data: data,
onSendProgress: (int sent, int total) {
if (total != -1) {
print((sent / total * 100).toStringAsFixed(0) + "%");
}
},
);
print(response.statusCode);
} catch (e) {
print(e);
}
Approach third -->
var request = new http.MultipartRequest("PUT", postUri);
request.headers['X-MS-BLOB-TYPE'] = 'BlockBlob';
request.headers['Content-Type'] = 'image/jpeg';
request.files.add(
new http.MultipartFile.fromBytes(
'picture',
await image.readAsBytes(),
),
);
request.send().then((response) {
uploadResponse.add(response.statusCode);
}, onError: (err) {
print(err);
});
Help here is much appreciated.
If you want to upload the image to Azure Blob Storage in the flutter application, you can use the Dart Package azblob to implement it. Regarding how to use the package, please refer to here.
For example
import 'package:image_picker/image_picker.dart';
import 'package:flutter/material.dart';
import 'package:azblob/azblob.dart';
import 'package:mime/mime.dart';
...
//use image_picker to get image
Future uploadImageToAzure(BuildContext context) async {
try{
String fileName = basename(_imageFile.path);
// read file as Uint8List
Uint8List content = await _imageFile.readAsBytes();
var storage = AzureStorage.parse('<storage account connection string>');
String container="image";
// get the mine type of the file
String contentType= lookupMimeType(fileName);
await storage.putBlob('/$container/$fileName',bodyBytes: content,contentType: contentType,type: BlobType.BlockBlob);
print("done");
} on AzureStorageException catch(ex){
print(ex.message);
}catch(err){
print(err);
}
Unfortunately, the multipart form is causing break of image. I don't know how it works on azure side, because there is little or no information about multipart uploads, but it's clearly broken because of multipart form. I replicated the problem in .net core application and whenever i am using multipart form data to upload image - it is broken. When i am using simple ByteArrayContent - it works. I couldn't find flutter equivalent to ByteArrayContent, so i am lost now :( The package mentioned by #Jim is useless for me, because i want to give clients sas url, so they have permission to upload image on client side. I do not want to store azure storage account secrets in flutter app.
EDIT. I found the solution to send raw byte data with Dio package. You can do that also with http package.
final dio = new Dio();
final fileBytes = file.readAsBytesSync();
var streamData = Stream.fromIterable(fileBytes.map((e) => [e]));
await dio.put(uploadDestinationUrl,
data: streamData,
options: Options(headers: {
Headers.contentLengthHeader: fileBytes.length,
"x-ms-blob-type": "BlockBlob",
"content-type": "image/jpeg"
}));

uploading image to backed from flutter error 401

Flutter image upload to laravel backed is returning 401 error. My backed have database fields name, middelName , and profilePic The api works fine on postman but on flutter picking image from gallery and camera its not working i have implemented internet permission on all manifests i used Vpn but error 401
here is flutter code
Future uploadImage() async{
final uri =Uri.parse("https://www.compaytarining.com/api/exrecise2/");
var request =http.MultipartRequest('POST',uri);
request.fields["name"]=nameController.text;
request.fields["middelName"] = mnameController.text;
var pic= await http.MultipartFile.fromPath("profilePic", _image.path);
request.files.add(pic);
var response = await request.send();
print(response.statusCode);
if(response.statusCode==200)
{
print('ImageUploaded');
}
else
{
print("Error");
}
}
Gallery Image
File _image;
final picker=ImagePicker();
Future getImage() async
{
final pickedImage=await picker.getImage(source: ImageSource.gallery);
setState(() {
_image=File(pickedImage.path);
});
}
Many thanks
Hello check it may be error is from your response which is when you return an api response may be u set it to return 401.

Flutter form builder package image picker firestore flutter

i am using FormBuilderImagePicker from package Flutter form builder
I want to use the img path but i am not able to do so
sending() async {
var storageimage =
FirebaseStorage.instance.ref().child('/google/google');
var task = storageimage.putFile();
imgurl = await (await task.onComplete).ref.getDownloadURL();
// await Firestore.instance.collection('twst').add(
// {
// 'img': imgurl.toString(),
// },
// );
}
i want to use that function with the imagepicker
but the problem is i am not able to find path to use putfile
To get the path of the FormBuilderImagePicker, the toString() method of the class prints the path.
Here is an example of how you can print in a container the Text field including FormBuilderImagePicker which have the path.
Then you will need to pass the image or file to the putFile method.
You can also use the ImagePicker pickImage class method to get the file.
sending() async {
File image;
try {
//Get the file from the image picker and store it
image = await ImagePicker.pickImage(source: ImageSource.gallery);
// Throws error when you don't select any image or when you don't have permissions
} on PlatformException catch (e) {
return;
}
//Create a reference to the location you want to upload to in firebase
StorageReference reference = FirebaseStorage.instance.ref().child("/google/google");
//Upload the file to Firebase
StorageUploadTask uploadTask = reference.putFile(image);
StorageTaskSnapshot taskSnapshot = await uploadTask.onComplete;
// Waits till the file is uploaded then stores the download URL
String url = await taskSnapshot.ref.getDownloadURL();
}