1

Heyy, i am trying to upload a cropped image to firebase. I would prefer to use the ionic native "image-picker" and "Crop". I really dont know how to upload the image after cropping it, because it only returns the path of the new image.

I have already tryed something like this. This worked, but i was not able to crop the image. But as i mentioned, i would prefer using the native tools anyways.

      export interface UploadData {
        name: string;
        filepath: string;
        size: number;
      }
  uploadFile(event: FileList) {        
      // The File object
      const file = event.item(0);        
      // Validation for Images Only
      if (file.type.split('/')[0] !== 'image') {
       console.error('unsupported file');
       return;
      }        
      // The storage path
      const path = `whatever/${new Date().getTime()}_${file.name}`;        
      // File reference
      const fileRef = this.storage.ref(path);        
      // The main task
      this.task = this.storage.upload(path, file, { customMetadata });        
      this.snapshot = this.task.snapshotChanges().pipe(        
        finalize(() => {
          // Get uploaded file storage path
          this.UploadedFileURL = fileRef.getDownloadURL();
          this.UploadedFileURL.subscribe(resp => {
            this.addImagetoDB({
              name: file.name,
              filepath: resp,
              size: this.fileSize
            });
          }, error => {
            console.error(error);
          });
        }),
        tap(snap => {
            this.fileSize = snap.totalBytes;
        })
      );
    }

    addImagetoDB(image: UploadData) {
        const id = this.db.createId();

        // Set document id with value in database
        this.imageCollection.doc(id).set(image).then(resp => {
          console.log(resp);
        }).catch(error => {
          console.log('error ' + error);
        });
    }
}

This is how i would like to do it. But i really have no idea, how to upload it at this point.

    pickImage() {
      this.imagePicker.getPictures(this.imagePickerOptions).then((results) 
    => {
        // tslint:disable-next-line: prefer-for-of
        for (let i = 0; i < results.length; i++) {
          this.cropImage(results[i]);
        }
      }, (err) => {
        alert(err);
      });
    }     
    cropImage(imgPath) {
      this.crop.crop(imgPath, { quality: 50 })
        .then(
          newPath => {
            // ?????
          },
          error => {
            alert('Error cropping image' + error);
          }
        );
    }

Sorry, i am very new to this stuff. Thanks for your help :)

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
moe ven
  • 33
  • 6
  • Doesn't seem like anyone is going to answer this one. I tried to write something last night but... I didn't really know the answer :P I've tried to figure this out for you yesterday and today but not managed to. Guess you need to start off with something simpler while you're learning. I cannot find any tutorials that explain this particular chain of tasks. – rtpHarry Aug 10 '19 at 13:18
  • Hmm, okay thats too sad :( But thanks for trying – moe ven Aug 12 '19 at 07:16
  • Yeah generally things trail off pretty fast so if you dont get an answer early on it's probably not coming. I have been looking into it further though. – rtpHarry Aug 12 '19 at 09:22

2 Answers2

1

It seems that you might be able to do this without the crop feature being needed.

These are the options according to the docs:

options = {
    // Android only. Max images to be selected, defaults to 15. If this is set to 1, upon
    // selection of a single image, the plugin will return it.
    maximumImagesCount: int,

    // max width and height to allow the images to be.  Will keep aspect
    // ratio no matter what.  So if both are 800, the returned image
    // will be at most 800 pixels wide and 800 pixels tall.  If the width is
    // 800 and height 0 the image will be 800 pixels wide if the source
    // is at least that wide.
    width: int,
    height: int,

    // quality of resized image, defaults to 100
    quality: int (0-100),

    // output type, defaults to FILE_URIs.
    // available options are 
    // window.imagePicker.OutputType.FILE_URI (0) or 
    // window.imagePicker.OutputType.BASE64_STRING (1)
    outputType: int
};

So you could use:

options = {
    maximumImagesCount: 3,
    width: 800,
    height: 600,
    quality: 50,
    outputType: 1
};

From what I've been researching you could then put the image into Firebase Storage using:

storageRef.putString("Your base64 string substring variable", 'base64');

I'm not sure if this is enough to get you fixed up but I thought I would post what I had found anyway.

rtpHarry
  • 13,019
  • 4
  • 43
  • 64
  • What do you think about something like this? Would it work on ios too? If i use the crop-funcionality: https://stackoverflow.com/questions/42156069/convert-local-image-to-base64-javascript – moe ven Aug 12 '19 at 11:16
  • I don't think you need that. The `outputType: 1` will give you an array of base64 encoded data. If you post the url to the crop library then I can look and see what options it supports? – rtpHarry Aug 12 '19 at 11:44
  • https://ionicframework.com/docs/native/crop seems like not very in detail – moe ven Aug 12 '19 at 13:19
  • ok yeah seems that if you want to use that then you cannot let the picker load the images for you because the crop doesn't accept base64. So you need to figure out how to upload a file to Firebase Storage from a path instead. I'll let you know if I find anything. – rtpHarry Aug 13 '19 at 05:14
  • It seems [you need a File or Blob](https://firebase.google.com/docs/storage/web/upload-files), which means you need to [convert a path to a file](https://forum.ionicframework.com/t/convert-path-to-file-or-blob-object-ionic/94364) using the [file](https://ionicframework.com/docs/native/file) / [cordova](https://github.com/apache/cordova-plugin-file#readFile) plugin. – rtpHarry Aug 13 '19 at 05:29
  • Okay thanks, i just tried that. It dosnt work for me. I have no idea why. I just posted my code below. Can you help me please? – moe ven Aug 13 '19 at 08:02
  • It seems like the 'readAsArrayBuffer' is not executing at all... But it throws no exception – moe ven Aug 13 '19 at 11:31
0

I just tried this, but it dosn´t work too. I have no idea why...

constructor(private imagePicker: ImagePicker, private crop: Crop,
    private file: File) {
      let storageDb = firebase.storage();
      this.storageRef = storageDb.ref();
  }


pickImage() {
  this.imagePicker.getPictures(this.imagePickerOptions).then((results) 
=> {
    // tslint:disable-next-line: prefer-for-of
    for (let i = 0; i < results.length; i++) {
      this.cropImage(results[i]);
    }
  }, (err) => {
    alert(err);
  });
}  


cropImage(imgPath) {
    this.crop.crop(imgPath, { quality: 50 })
      .then(
        newPath => {
          try {
            let n = newPath.lastIndexOf("/");
            let x = newPath.lastIndexOf("g");
            let nameFile = newPath.substring(n + 1, x + 1);
            this.file.readAsArrayBuffer(newPath, nameFile).then((res) => {
              let blob = new Blob([res], { type: "image/jpeg" });
              var uploadTask = this.storageRef.child('images/' + this.event.id).put(blob);
              uploadTask.on('state_changed', (snapshot) => {
                let url = uploadTask.snapshot.downloadURL;
                this.croppedImagepath = url;
              }, (error) => {
                alert("error: " + error);
              }, () => { 
                alert("uploaded");
                let url = uploadTask.snapshot.downloadURL;
                this.croppedImagepath = url;
              })
            })
          }
          catch (z) {
            alert('error beim erstellen des blobs' + z);
          }
        },
        error => {
          alert('Error cropping image' + error);
        }
      );
  }
moe ven
  • 33
  • 6