Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to get Image and File? #8

Closed
clus90 opened this issue Apr 30, 2020 · 4 comments
Closed

Is it possible to get Image and File? #8

clus90 opened this issue Apr 30, 2020 · 4 comments

Comments

@clus90
Copy link

clus90 commented Apr 30, 2020

Hi, I am using this library on a form, I would like to show the Image widget when the user selects the image (I've accomplished this), but when I submit the form I need the File info to send it to Firebase and it seems the only way to get both is requesting the image twice to the user, which is kind of annoying.

Thanks in advance,

@jaxnz
Copy link

jaxnz commented May 1, 2020

I had the same issue - here's how I overcame it (it was before @Ahmadre updated to pick File).

Sorry - I haven't modified code so might be a little messy. Hopefully this may help. I'm hoping to re-integrate image_picker_web back in to clean the code up when I get some time.

Note: import 'dart:html' as html;

Button for Picker:

                    ThemedButton(
                      child: Text(
                        'Upload User Logo',
                        style: TextStyle(color: Colors.white),
                      ),
                      onPressed: () async {
                        //Upload Image as File
                        imageFile = await uploadImage();
                        //Convert File to Image
                        _image = await convertFileToImage(file: imageFile);
                        //Get Image Name
                        MediaInfo getInfo = await convertFileGetName(file: imageFile);
                        fileName = getInfo.fileName;
                        //Show new image on screen
                        setBottomSheetState(() {
                          image = _image;
                          if(image != null){
                            setBottomSheetState(() {
                              logoUpload = '';
                            });
                          }
                        });
                      },
                    ),

uploadImage()

Future<html.File> uploadImage() async {
  html.InputElement uploadInput = html.FileUploadInputElement();
  uploadInput.click();
  await uploadInput.onChange.first;
  final files = uploadInput.files;
  final fileImage = files[0];
  return fileImage;
}

convertFileToImage()

Future<Image> convertFileToImage({@required html.File file}) async {
  final Map<String, dynamic> data = {};
  final reader = html.FileReader();
  reader.readAsDataUrl(file);
  await reader.onLoad.first;
  final encoded = reader.result as String;
  final stripped = encoded.replaceFirst(RegExp(r'data:image/[^;]+;base64,'), '');
  final fileName = file.name;
  final filePath = file.relativePath;
  data.addAll({
    'name': fileName,
    'data': stripped,
    'data_scheme': encoded,
    'path': filePath
  });

final imageName = data['name'];
final imageData = base64.decode(data['data']);
return Image.memory(imageData, semanticLabel: imageName,);
}

convertFileGetName()

Future<MediaInfo> convertFileGetName({@required html.File file}) async {
  final Map<String, dynamic> infoData = {};
  final reader = html.FileReader();
  reader.readAsDataUrl(file);
  await reader.onLoad.first;
  final fileName = file.name;
  infoData.addAll({
    'name': fileName,
  });

  MediaInfo webImageInfo = MediaInfo();
  webImageInfo.fileName = infoData['name'];
  return webImageInfo;

}

Add User Button

                      ThemedButton(
                        child: buttonProgress(text: 'Add User', state: spinner),
                        onPressed: () async {
                          if (_formKey.currentState.saveAndValidate()) {
                            if (imageFile != null) {
                              //progress indicator
                              setBottomSheetState(() {
                                spinner = 1;
                              });
                              userName = _formKey.currentState.fields['Name'].currentState.value;
                              userEmail = _formKey.currentState.fields['Email'].currentState.value;
                              userPassword = _formKey.currentState.fields['Password'].currentState.value;
                              try {
                                //create user in FireAuth
                                final result = await AuthService().register(userEmail, userPassword);
                                //confirm creation
                                if (result != null) {
                                  //Convert to FirebaseUser to user
                                  FirebaseUser newUser = result.user;
                                  //Upload File with filename and return location
                                  location = await uploadProfilePhoto(imageFile, imageName: fileName);
                                  //Pass new user ID through to users Collection to link UserData to this user in Firestore
                                  await UserDatabaseService(uid: newUser.uid).createUser(userID: newUser.uid, name: userName, email: userEmail, displayPhoto: location);
                                  Navigator.of(context).pop();
                                  setBottomSheetState(() {
                                    spinner = 0;
                                  });
                                  //TODO if statement for update confirmation
                                  final snackBar = SnackBar(content: Text('The New user has been created!'),duration: Duration(seconds: 5),);
                                  Scaffold.of(context).showSnackBar(snackBar);
                                } else {
                                  setBottomSheetState(() {
                                    firebaseError = result.toString();
                                    spinner = 0;
                                  });
                                }
                              } catch (e) {
                                setBottomSheetState(() {
                                  firebaseError = e;
                                  spinner = 0;
                                });
                              }
                            } else {
                              final String _uploadError = 'Please Upload a User Photo';
                              setBottomSheetState(() {
                                logoUpload = _uploadError;
                              });
                            }
                          }
                        },
                      ),

uploadProfilePhoto()

String url;

Future<String> uploadProfilePhoto(html.File image, {String imageName}) async {
  try {
    //Upload Profile Photo
    fb.StorageReference _storage = fb.storage().ref('displayPhotos/$imageName');
    fb.UploadTaskSnapshot uploadTaskSnapshot = await _storage.put(image).future;
    // Wait until the file is uploaded then store the download url
    var imageUri = await uploadTaskSnapshot.ref.getDownloadURL();
    url = imageUri.toString();
  } catch (e) {
    print(e);
  }
  return url;
}

@Ahmadre
Copy link
Owner

Ahmadre commented May 1, 2020

Guys this was already answered:

#5 (comment)

This has nothing to do with my package. In Image_Picker for native mobile it's the same: it's returning a File! The plus in this package is, that you got more options. But it seems that a lot of people gets confused why they got more options.

Just have a look at the answer above and the related GIST.

I'll close this issue, because it has nothing to do with the package.

@Ahmadre Ahmadre closed this as completed May 1, 2020
@clus90
Copy link
Author

clus90 commented May 1, 2020

Thank you @jaxnz !.. This is great, I only needed the convertFileToImage method and works perfectly. They should add this method to the library.

@Ahmadre
Copy link
Owner

Ahmadre commented May 16, 2020

@clus90 It is in this library 😄

You just need MediaInfo for that. There's no need for such boilerplate reading again.

import 'dart:html' as html;
 
import 'package:mime_type/mime_type.dart';
import 'package:path/path.dart' as Path;
import 'package:image_picker_web/image_picker_web.dart';
import 'package:flutter/material.dart';

 html.File _cloudFile;
 var _fileBytes;
 Image _imageWidget;
 
 Future<void> getMultipleImageInfos() async {
    var mediaData = await ImagePickerWeb.getImageInfo;
    String mimeType = mime(Path.basename(mediaData.fileName));
    html.File mediaFile =
        new html.File(mediaData.data, mediaData.fileName, {'type': mimeType});

    if (mediaFile != null) {
      setState(() {
        _cloudFile = mediaFile;
        _fileBytes = mediaData.data;
        _imageWidget = Image.memory(mediaData.data);
      });
    }
  }

This will get you in one run every 3 types :)

PS: I will add this to the readme for others out there. Thank you guys for asking this question 👍

@jaxnz jaxnz mentioned this issue May 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants