0
votes

I have an ionic 3 app; I am working on upload profile picture functionality. In this, I want to select the image from either gallery or capture image using the camera. After that, I will have two images/image_paths. I want to upload these two images along with user_id, access_token

Select Image From Gallery let option = { title: 'Select Picture', message: 'Select Least 1 Picture', maximumImagesCount: 1, outType: 0 };

this.imagePicker.getPictures(option).then(results => {
          for (var i = 0; i < results.length; i++) {
            // alert('Image URI: ' + results[i]);
            this.imageSelected = "data:image/jpeg;base64," +results[i];
            // this.imageSelected = results[i];
            let option = {
              quality: 100,
              targetHeight: 400,
              targetWidth: 400,
            };
            this.crop.crop(this.imageSelected, option).then((data) => {
              this.imageCropped = "data:image/jpeg;base64," +data;
              // alert(this.imageCropped);
              this.saveProfileImage(this.imageSelected, this.imageCropped);
            }, err => {
              this.imageCropped = '';
              alert(err);
            });
          }
        }, err => {
          this.imageSelected = '';
          alert('Error' + err);
        })

Select an image from the camera let options: CameraOptions = { quality: 100, destinationType: this.camera.DestinationType.DATA_URL, encodingType: this.camera.EncodingType.JPEG, mediaType: this.camera.MediaType.PICTURE }

this.camera.getPicture(options).then((imageData) => {
          // alert(imageData);
          this.imageSelected = "data:image/jpeg;base64," +imageData;
          let option = {
            quality: 100,
            targetHeight: 400,
            targetWidth: 400,
          };
          this.crop.crop(this.imageSelected, option).then((data) => {
            this.imageCropped = "data:image/jpeg;base64," +data;
            this.saveProfileImage(this.imageSelected, this.imageCropped);
          }, err => {
            this.imageCropped = '';
            alert(err);
          });
        }, (err) => {
          this.imageSelected = '';
          alert('Error' + err);
        });

Please see the above code and if it is right, suggest me how to write upload function with either form data or any another method

[This is screenshot of first way i tried uploading images][1]

This is a screenshot of the second way I tried uploading images

2
please make sure that you need to upload file? and u create any function or not?Utpaul
you want to send crop image to server or not?Utpaul
@Utpaul yes i want to upload both images to server along with some data like user_id, access_token etc So that i will use both images cropped and full image in application as per suits.Pranav Mandlik
crop as well a without crop data or only cropping image dataUtpaul
cropped image as well as uncropped imagePranav Mandlik

2 Answers

4
votes

Even I was facing the same problem some time back, and did not find proper solution on the web. Below is the solution, which I found after some research and works perfectly fine, not just for images, but also for other files. Since Question asked is about the images, I will explain the answer w.r.t to images. (Except choosing the files, the procedure remains same for other files).

  1. You can choose the image using the Cordova camera plugin, After installing the plugin and importing it on app.module.ts and adding it to provider, you can use below code to choose images from camera or from gallery. ActionSheetController would be the best way to give option to user, to pick image from gallery or from camera.

code for choosing the image from camera:

const options: CameraOptions = {
  quality: 100,
  correctOrientation: true,
  cameraDirection: 1,
}

this.camera.getPicture(options).then((imageData) => {
  console.log("IMAGE DATA IS", imageData);
}).catch(e => {
  console.log("Error while picking from camera", e)
})

code for choosing the image from gallery:

  var options = {
  sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
  destinationType: this.camera.DestinationType.FILE_URI,
};
this.camera.getPicture(options).then((imageData) => {
  console.log("IMAGE DATA IS", imageData);
}).catch(e => {
  console.log("Error while picking from gallery", e)
});
  1. After choosing the image,you need to convert it to base64 using com-badrit-base64 plugin. After installing the plugin and importing it on app.module.ts and adding to provider list, Just pass the output of camera plugin to this, the chosen image will be converted into base64.

Below is the code snippet to convert the chosen image to base64,I have written it for camera, it remains same for gallery. After converting the image to base64 push it to an array. Now you are able to choose multiple images and store it's value in array.

  var options = {
  sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
  destinationType: this.camera.DestinationType.FILE_URI,
};
this.camera.getPicture(options).then((imageData) => {
  console.log("IMAGE DATA IS", imageData);

  let filePath: string =imageData
    this.base64.encodeFile(filePath).then((base64File: string) => {
    console.log(base64File);
      this.base64File.push(base64File);
    }, (err) => {
    console.log(err);
    });

}).catch(e => {
  console.log("Error while picking from gallery", e)
});
  1. Now send the data to server via your API. You can use cordova-plugin-advanced-http or Angular-http to achieve it. The API should take images in the format of array, along with other parameters. As base64 images will be a string with bigger length, formData or row is recommended over the url-encoded format, for post method of REST.
  2. Now in back-end the body will be parsed and the image array will be extracted. In all the popular back-end languages(Java, PHP, NodeJS, C# etc), which are used for writing API's,there are free libraries to convert base64 image to actual image.
  3. Whola, that's it, now you are be able to send multiple images to your server via API. Along with images, if your trying to choose files of any other MIME type (pdf, doc, docx etc) you can use the same approach for it.

I have also created a git hub repository at: https://github.com/coolvasanth/upload-multiple-image-files-in-Ionic-3-4/blob/master/README.md

1
votes

First of all you need to create an formData object.

private formData:any = {
    'user_id':this.userId,
    'access_token':this.accessToken,
    'device_id':this.devId,
    'device_type':this.devType,
    'registration_ip':this.ipAdd,
    'image':'',
    'crop_image'
  };

Need to change imagePicker

this.imagePicker.getPictures(option).then(results => {

  for (var i = 0; i < results.length; i++) {
    // alert('Image URI: ' + results[i]);

    //set it results[i] in unCropImages

    this.data.image= "data:image/jpeg;base64," +results[i];

    this.imageSelected = results[i];
    let option = {
      quality: 100,
      targetHeight: 400,
      targetWidth: 400,
    };

    this.crop.crop(this.imageSelected, option).then((data) => {
      this.imageCropped = "data:image/jpeg;base64," +data;
      // alert(this.imageCropped);

      //set it imageCropped in cropImage

      this.data.crop_image= this.imageCropped;

      //No need to this function

      this.saveProfileImage();

    }, err => {
      this.imageCropped = '';
      alert(err);
    });
  }
}, err => {
  this.imageSelected = '';
  alert('Error' + err);
})

Need to change in camera

this.camera.getPicture(options).then((imageData) => {
          // alert(imageData);
          this.imageSelected = "data:image/jpeg;base64," +imageData;

          this.data.image= "data:image/jpeg;base64," +results[i];

          let option = {
            quality: 100,
            targetHeight: 400,
            targetWidth: 400,
          };
          this.crop.crop(this.imageSelected, option).then((data) => {
            this.imageCropped = "data:image/jpeg;base64," +data;

            this.data.crop_image= this.imageCropped;

          this.saveProfileImage();
          }, err => {
            this.imageCropped = '';
            alert(err);
          });
        }, (err) => {
          this.imageSelected = '';
          alert('Error' + err);
        });

Setup POST method

First of all you need to inject HttpClientModule in import section of app.module.ts file

Then inject private http: HttpClient inside constructor in saveProfileImage() funtion class

change in saveProfileImage()

saveProfileImage(){

  return new Promise((resolve, reject) => {
    this.http.post('Your URL', JSON.stringify(this.formData))
      .subscribe(res => {
        resolve(res);
       //success 
      }, (err) => {
        reject(err);
        //fail
      });
  });

}