Flutter Sending Image via Mailer - firebase

I'm trying to find a solution for my code. I'm trying to send mail with image attachment but I couldn't figured out how to do. I searched nearly all topics in this website but none of it helped me.
Without using attachment, I'm able to send email but when I use attachment and trying to send my image, nothing happens. I hid private information from the code.
File newImage;
uploadImage() async {
final _storage = FirebaseStorage.instance;
final _picker = ImagePicker();
PickedFile image;
image = await _picker.getImage(source: ImageSource.camera);
var file = File(image.path);
String filName = basename(file.path);
// Upload to Firebase
var snapshot = await _storage.ref().child(filName).putFile(file).onComplete;
var downloadURL = await snapshot.ref.getDownloadURL();
setState(() {
imageUrl = downloadURL;
newImage = image; // PickedFile can't be assigned to variable type File
});
}
main(message) async{
var options = new SmtpOptions()
// Hidden
var transport = new SmtpTransport(options);
var envelope = new Envelope()
..from = 'example#mail.com'
..fromName = 'example'
..recipients = ['example2#mail.com']
..subject = 'example'
..attachments.add(new Attachment(file: new File(newImage))) // File can't be assigned to parameter type 'String'
..text = "$message";
transport.send(envelope)
.then((_) => print('email sent!'))
.catchError((e) => print('Error: $e'));
}

You can try this code instead:
..attachments.add(new Attachment(file: new File(newImage.path)))

Related

Is there any way to save flutter_tts file to firebase storage?

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;
}

How to get a Stream of download url in firebase flutter

i want to create a stream of firebase storage download link for all the images
firebase_storage.FirebaseStorage storage =
firebase_storage.FirebaseStorage.instance;
firebase_storage.Reference ref =
storage.ref().child('images');
firebase_storage.ListResult result = await ref.listAll();
result.items.forEach((firebase_storage.Reference ref) async* {
print('Found file: $ref');
yield (await ref.getDownloadURL()).toString();
});
}
the snapshot data is null
if i create with future it seems to work when i add all the urls in a list and give to listview builder
but i cant get each string through stream
I've had problems with ForEach and await getDownloadUrl(). Try using a for loop instead.
for (Reference refin result.items) async* {
print('Found file: $ref');
yield (await getDownloadUrl().toString());
}
First thing first create a instance of FirebaseStorage
final _firestorage = FirebaseStorage.instance;
after then we need ref. for get image from storage.
final ref = _firestorage.ref().child('image');
and then we can create image's url.
var imageURL = await ref.getDownloadURL();
and try this.
print(imageURL);
if you wanna get this codes into fully method:
String getImageURL(){
final _firestorage = FirebaseStorage.instance;
final ref = _firestorage.ref().child('image');
var imageURL = await ref.getDownloadURL();
if(imageURL != null){
return imageURL;
}else{
print("Couldn't load image");
}
}
Also you can get this image with StreamBuilder or FutureBuilder etc. for get more about FirebaseStorage check it out this documentation

How to rebuild profile picture widget on changes to file in Firebase Storage (Flutter)

I am trying to build a profile picture widget in Flutter that allows the user to upload an image to Firebase storage and retrieve that image once it has been uploaded. My problem is that I call the _getImage() Function in initState() so anytime the user uploads a new photo the widget isn't rebuilt with the new photo unless the app is restarted. Is there a 'stream' like method I can use to listen to changes in a Firebase Storage location and rebuild a widget accordingly?
I use ImagePicker to get my image from gallery.
_pickImage() async {
final selected = await ImagePicker().getImage(source: ImageSource.gallery);
setState(() {
_imageFile = File(selected.path);
});
_uploadFile(_imageFile);}
After the photo is chosen, it is uploaded to Firebase Storage.
_uploadFile(File _imageFile) async{
var user = await FirebaseAuth.instance.currentUser();
var storageRef = _storage.ref().child('user/profile/${user.uid}');
var uploadTask = storageRef.putFile(_imageFile);
}
Then to retrieve the image, I call the _getImage() function in initState().
void initState() {
super.initState();
_getImage();
}
the _getImage() funtion.
_getImage() async {
var user = await FirebaseAuth.instance.currentUser();
var photoReference = _storage.ref().child("user/profile/${user.uid}");
photoReference.getData(1000000000).then((data){
this.setState(() {
imageFile = data;
});
}).catchError((onError){
print('error');
}); }
here is a example
final image = await ImagePicker()
.pickImage(source: ImageSource.gallery);
if (image == null) return;
FirebaseStorage storage = FirebaseStorage.instance;
Reference ref = storage.ref().child("images/${DateTime.now()}");
UploadTask uploadTask = ref.putFile(File(image.path));
uploadTask.then((res) async {
String fileurl = await (await uploadTask).ref.getDownloadURL();
return fileurl;
You have to upload image on firebase then retrieve the image url
then you can call it on user profile

Flutter: http post upload an image (Futuer<file>)

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);
});
}

How to make an image appear immediately after being added to firebase without restarting Flutter

My code is normal, but if I add data to Firebase the image does not appear, but if it has restarted the application appears by itself and the image successfully appears, how to resolve it?
child: new Container(
child: Image.network(
'${doc.data["image"]}' + '?alt=media',),
width: 170,
height: 120,
),
here's the code to add it
void createData() async {
DateTime now = DateTime.now();
String format = DateFormat('dd:mm:yy').format(now);
var fullImageName = 'foto-$format' + '.jpg';
var fullImageName2 = 'foto-$format' + '.jpg';
final StorageReference ref =
FirebaseStorage.instance.ref().child(fullImageName);
final StorageUploadTask task = ref.putFile(image);
var part1 =
'https://firebasestorage.googleapis.com/v0/b/db-tubes.appspot.com/o/';
var fullPathImage = part1 + fullImageName2;
print(fullPathImage);
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
DocumentReference ref = await db
.collection('resep')
.add({'nama': '$nama', 'resep': '$resep', 'image': '$fullPathImage', 'email' : widget.email});
setState(() => id = ref.documentID);
Navigator.of(context).pop();
}
}
StorageUploadTask task is a Future, so you need to wait upload task to complete to get the URL
try this
void createData() async {
DateTime now = DateTime.now();
String format = DateFormat('dd:mm:yy').format(now);
var fullImageName = 'foto-$format' + '.jpg';
var fullImageName2 = 'foto-$format' + '.jpg';
final StorageReference ref =
FirebaseStorage.instance.ref().child(fullImageName);
final StorageUploadTask task = ref.putFile(image);
// Wait upload task to complete
final StorageTaskSnapshot downloadUrl =
(await task.onComplete);
// Get image uRL
final String url = (await downloadUrl.ref.getDownloadURL());
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
DocumentReference ref = await db
.collection('resep')
.add({'nama': '$nama', 'resep': '$resep', 'image': '$url', 'email' : widget.email});
setState(() => id = ref.documentID);
Navigator.of(context).pop();
}
}
}
This is just a demonstration for your idea.
Future uploadFile() async {
StorageReference storageReference = FirebaseStorage.instance
.ref()
.child('chats/${Path.basename(_image.path)}}');
StorageUploadTask uploadTask = storageReference.putFile(_image);
await uploadTask.onComplete;
print('File Uploaded');
storageReference.getDownloadURL().then((fileURL) {
setState(() {
_uploadedFileURL = fileURL;
});
});
}
In the setState put that URL into local variable and use that local variable to your image file as network and it will automatically fetch on the next Dom creation.
If the image doesn't update when refreshing the widget, I see a common issue here with writing files to the same address/name in firebase storage.
Somehow image widgets don't understand that the image has been updated if the file name is the same as the old file name like: "2019-11-19-file.jpg". If you write to that again, it won't update.
In that case, you should make the filename have a random component to it, like a UTC milliseconds timestamp name ("1234512312-file.jpg"), or add "&random=[insert random number here]" to the end of your image URL string.

Resources