Upload image to server using Ionic 5

I’ve been trying to upload a image to the server using Ionic 5 without any luck.
After taking a image with the camera or selecting a image from the galery, and try to upload it, it returns empty (No image selected.)

Ionic code :

  createFileName() {
    const d = new Date(),
      n = d.getTime(),
      newFileName = n + '.jpg';
    return newFileName;
  }

  pathForImage(img: string) {
    if (img === null) {
      return '';
    } else {
      return this.file.dataDirectory + img;
    }
  }


  async selectImage() {

    let buttonLabels = ['Select from galery', 'Use camera'];

    const options: ActionSheetOptions = {
      title: 'Make a choice',
      buttonLabels: buttonLabels,
      addCancelButtonWithLabel: 'Cancel',
      androidTheme: 4
    }

    this.actionSheet.show(options).then((buttonIndex: number) => {
      if (buttonIndex == 1) {
        this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY);
      } else if (buttonIndex == 2) {
        this.takePicture(this.camera.PictureSourceType.CAMERA);
      }
    });

  }


  copyFileToLocalDir(namePath: string, currentName: string, newFileName: string) {

    this.file.copyFile(namePath, currentName, this.file.dataDirectory, newFileName).then(success => {
      this.lastImage = newFileName;
    }, error => {
      console.log(error);
    });

  }


  takePicture(sourceType: any) {

    const options: CameraOptions = {
      quality: 100,
      sourceType: sourceType,
      saveToPhotoAlbum: false,
      correctOrientation: true,
      cameraDirection: 1,
      allowEdit: true,
      targetHeight: 300,
      targetWidth: 300
    };

    this.camera.getPicture(options).then(imageData => {

      this.clickedImage = (<any>window).Ionic.WebView.convertFileSrc(imageData);


      if (this.platform.is('android') && sourceType === this.camera.PictureSourceType.PHOTOLIBRARY) {

        this.filePath.resolveNativePath(imageData).then(filePath => {
          const correctPath = filePath.substr(0, filePath.lastIndexOf('/') + 1);
          const currentName = imageData.substring(imageData.lastIndexOf('/') + 1, imageData.lastIndexOf('?'));
          this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
        });

      } else {

        const currentName = imageData.substr(imageData.lastIndexOf('/') + 1);
        const correctPath = imageData.substr(0, imageData.lastIndexOf('/') + 1);
        this.copyFileToLocalDir(correctPath, currentName, this.createFileName());

      }

      this.uploadImageData();

    });

  }


  uploadImageData() {

    var targetPath = this.pathForImage(this.lastImage);
    var filename = this.lastImage;


    const fileTransfer: FileTransferObject = this.transfer.create();

    let options: FileUploadOptions = {
      fileKey: "file",
      fileName: filename,
      chunkedMode: false,
      mimeType: "multipart/form-data",
      params : {'fileName': filename}
    }


    fileTransfer.upload(targetPath, upload_url, options)
      .then((data) => {

        this.newdata = JSON.parse(data.response);
        if (this.newdata.success) {
          this.global.presentAlert("Success", this.newdata.message);
        } else {
          this.global.presentAlert("Error", this.newdata.message);
        }

      }, (err) => {
        this.global.presentAlert("Error", JSON.stringify(err));
      })

  }

php code:

<?php

$xresponse = 0;
$xmessage = "";

$emparray = array();

if ( !empty( $_FILES ) ) 
{

    $target_path = urldecode($_FILES["file"]["name"]);
    $filename = stripslashes($target_path);
    $image_name = time() . "_" . $filename;

    if ( move_uploaded_file( $_FILES['file']['tmp_name'], "/uploads/profile/" . $image_name ) ) {

        $success = true;
        $message = "Upload success";

    } else {

        $success = false;
        $message = $image_name;

    }

} else {

    $success = false;
    $message = "No image selected.";

}


echo json_encode( 
    $emparray = array(
        'success' => $success,
        'message'=> $message
    )
);

html code:

<ion-header class="pages">
  <ion-toolbar class="bg-grad-lightblue">
    <ion-title>
      <span>My profile</span>
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content class="bg-lightblue">

  <section class="app-container">
    <ion-grid class="ptop">
      <ion-row>
        <ion-col size="12">
          <ion-avatar class="avatar_circle">
            <img src="{{this.img}}" alt="" [hidden]="clickedImage">
            <img [src]="clickedImage" [hidden]="!clickedImage" />
          </ion-avatar>

          <ion-card>
            <ion-card-content>
              <ion-button color="grad-btn-small bg-grad-gray" expand="block" (click)="selectImage()">
                <span class="ion-text-left">Upload image</span></ion-button>
            </ion-card-content>
          </ion-card>

        </ion-col>
      </ion-row>
    </ion-grid>
  </section>

</ion-content>

ionic info:

Ionic:

   Ionic CLI                     : 6.12.0 (C:\Users\User\AppData\Roaming\npm\node_modules\@ionic\cli)
   Ionic Framework               : @ionic/angular 5.3.1
   @angular-devkit/build-angular : 0.901.12
   @angular-devkit/schematics    : 9.1.12
   @angular/cli                  : 9.1.12
   @ionic/angular-toolkit        : 2.3.0

Cordova:

   Cordova CLI       : 10.0.0
   Cordova Platforms : 6.0.0, android 9.0.0, browser
   Cordova Plugins   : cordova-plugin-ionic-keyboard 2.2.0, cordova-plugin-ionic-webview 4.2.1, (and 18 other plugins)

Utility:

   cordova-res : 0.14.0
   native-run  : 1.2.2

System:

   NodeJS : v14.4.0 (C:\Program Files\nodejs\node.exe)
   npm    : 6.14.5
   OS     : Windows 10

Can someone help me with this or point me in the right direction.

Thank you

I would suggest using HttpClient instead of Cordova File Transfer here. You can simply post a Blob.

1 Like

Can we see the code when you use your fonction uploadImageData() ?

Hello Marcel, what do you mean? it’s in my first post

Hi @rapropos, i have changed my code to this:

takePicture(sourceType: any) {

    const options: CameraOptions = {
      quality: 100,
      sourceType: sourceType,
      saveToPhotoAlbum: false,
      correctOrientation: true,
      cameraDirection: 1,
      allowEdit: true,
      targetHeight: 300,
      targetWidth: 300
    };

    this.camera.getPicture(options).then(imageData => {

      this.clickedImage = this.webview.convertFileSrc(imageData);


      if (this.platform.is('android') && sourceType === this.camera.PictureSourceType.PHOTOLIBRARY) {

        this.filePath.resolveNativePath(imageData).then(filePath => {
          const correctPath = filePath.substr(0, filePath.lastIndexOf('/') + 1);
          const currentName = imageData.substring(imageData.lastIndexOf('/') + 1, imageData.lastIndexOf('?'));
          this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
        });

      } else {

        const currentName = imageData.substr(imageData.lastIndexOf('/') + 1);
        const correctPath = imageData.substr(0, imageData.lastIndexOf('/') + 1);
        this.copyFileToLocalDir(correctPath, currentName, this.createFileName());

      }

    });

  }



  pathForImage(img) {
    if (img === null) {
      return '';
    } else {
      let converted = this.webview.convertFileSrc(img);
      return converted;
    }
  }


  createFileName() {
    const d = new Date(),
      n = d.getTime(),
      newFileName = n + '.jpg';
    return newFileName;
  }

  copyFileToLocalDir(namePath, currentName, newFileName) {
    this.file.copyFile(namePath, currentName, this.file.dataDirectory, newFileName).then(
      success => {
        this.lastImage = newFileName;

        let filePath = this.file.dataDirectory + this.lastImage;
        let resPath = this.pathForImage(filePath);

        let newEntry = {
          name: this.lastImage,
          path: resPath,
          filePath: filePath
        };

        this.startUpload(newEntry);

      },
      error => {
        this.global.presentAlert("Error", "Error while storing file.");
      });
  }




  startUpload(imgEntry) {
    this.file.resolveLocalFilesystemUrl(imgEntry.filePath)
      .then(entry => {
        (<FileEntry>entry).file(file => this.readFile(file))
      })
      .catch(err => {
        this.global.presentAlert("Error", "Error while reading file.");
      });
  }



  readFile(file: any) {
    const reader = new FileReader();
    reader.onload = () => {
      const formData = new FormData();
      const imgBlob = new Blob([reader.result], {
        type: file.type
      });
      formData.append('file', imgBlob, file.name);
      this.uploadImageData(formData);
    };
    reader.readAsArrayBuffer(file);
  }



  uploadImageData(formData: FormData) {

    this.httpx.post(uploadURL, formData)
      .pipe(
        finalize(() => {
          this.global.presentAlert("Success", "finalize");
        })
      )
      .subscribe(res => {


        this.global.presentAlert("subscribe", "subscribe");

      });
  }

the finalize alert will show up but the subscribe won’t

What does the server have to say? Is anything going across the wire? Are there any uncaught exceptions in the JavaScript console?

OK sorry !
I needed for time to read your code.

My advices :

  • keep the FileTransfer plugin
  • mimeType: ‘image/jpeg’
  • your function uploadImageData(), try to transform it into

uploadImageData(targetPath: string){}

and when you call this function

this.uploadImageData(imageData);

Good luck !

1 Like

thank you @Marcel64 i’ve followed your advice and its working.

1 Like