Josep Alacid
Josep Alacid

Reputation: 1092

ionic 3 upload image from camera NOT USING file, file-transfer, file-upload plugins

I would like to upload an image to my back-end using FormData, but as Ionic DEVAPP and Ionic VIEW does not support file, file-transfer and file-upload plugins, I need to do it using only Angular Http or HttpClient.

When using DestinationType.FILE_URI, i can get the internal url from the file and display it on a img object, but I can't create a typescript File object from this url without the native file, file-path and file-transfer plugins.

getImage() {
const options: CameraOptions = {
  quality: 100,
  destinationType: this.camera.DestinationType.FILE_URI,
  sourceType: this.camera.PictureSourceType.PHOTOLIBRARY
}

this.camera.getPicture(options).then((imageData) => {
  this.imageURI =  this.sanitizer.bypassSecurityTrustUrl(imageData)
}, (err) => {
  console.log(err)
  this.presentToast(err)
})

}

using this template

<ion-content padding>
  <ion-item>
    <p>{{imageFileName}}</p>
    <button ion-button color="secondary" (click)="getImage()">Get Image</button>
  </ion-item>
  <ion-item>
    <h4>Image Preview</h4>
    <img style="display:block" [src]="imageURI" *ngIf="imageURI" alt="Ionic File" width="300" />
  </ion-item>
  <ion-item>
    <button ion-button (click)="uploadFile()">Upload</button>
  </ion-item>
</ion-content>

When using DestinationType.DATA_URL I can display the image but can not create the typescript File object needed with the original file name to append the image to the FormData used on my upload service at my Ionic App.

It seems I can find a way to create this typescript File object with the original filename from FILE_URI and a the base64 encoded data from DATA_URL using the camera.getPicture from the cordova camera native plugin.

Service to upload the file to my back-end just uses this approach:

postImage(image: File): Observable<any> {
        const formData = new FormData()
        .append('file', image, image.name)
        }
        return this.httpClient.post<any>(this.myUrl,formData)
    }

Both getImage from component myPage.ts and postImage from uploadservice.ts work fine, but I can't find a way to create the File object from camera.getPicture imageData

Upvotes: 7

Views: 3850

Answers (3)

Diego Arboleda
Diego Arboleda

Reputation: 82

If you don't want to use native plugins, you can always use angular. For this case use an ion input file:

<ion-input type="file"></ion-input>

And do the rest with angular: https://www.academind.com/learn/angular/snippets/angular-image-upload-made-easy/

You can use this example:

https://github.com/diegogplfree/Ionic3-fileupload-non-native

Upvotes: -2

Nifal Nizar
Nifal Nizar

Reputation: 963

I had the same issue and did like this and its works for me. but one thing to be note i'm not showing the selected image first. After uploading only its visible.

openImage() {
const options: CameraOptions = {
  quality: 100,
  destinationType: this.camera.DestinationType.FILE_URI,
  sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
  correctOrientation: true,
  allowEdit: false
};

this.camera.getPicture(options).then(imageData => {
  this.ImageFile = imageData;
}, err => {
  this.commonProvider.showToast('Error occured while opening the image' + err);
});

}

upload(msg: string) {
this.businessProvider.upload(this.Id, this.ImageFile)
  .then(
    data => {
      let response = JSON.parse(data["response"]);
      if (response.code === '1') {
        this.commonProvider.showToast('Business successfully ' + msg);
        this.navCtrl.pop();
      } else {
        this.commonProvider.showToast(response.message);
      }
      this.commonProvider.dismissLoader();
    },
    error => {
      this.commonProvider.showToast(JSON.stringify(error));
      this.commonProvider.dismissLoader();
    }
  );

}

This my business provider

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { ErrorObservable } from 'rxjs/observable/ErrorObservable';
import { catchError } from 'rxjs/operators';
import { Constant } from '../app/app.constants';
import { AuthenticationProvider } from '../providers/authentication';
import { FileTransfer, FileUploadOptions, FileTransferObject } from '@ionic-native/file-transfer';

@Injectable()
export class BusinessProvider {

  private actionUrl: string;

  constructor(
    private http: HttpClient,
    private auth: AuthenticationProvider,
    private constant: Constant,
    private transfer: FileTransfer
  ) {
    this.actionUrl = this.constant.getServerWithApiUrl() + 'Business/';
  }


  upload(Id: number, ImageFile): any {
    const fileTransfer: FileTransferObject = this.transfer.create();
    const headers = this.auth.getHeader();
    let options: FileUploadOptions = {
      fileKey: 'ionicfile',
      fileName: 'ionicfile.jpg',
      chunkedMode: false,
      mimeType: "image/jpeg",
      headers: { headers }
    }
    return fileTransfer.upload(ImageFile, this.actionUrl + 'Upload/' + Id, options);
  }

}

Upvotes: -1

mahi-man
mahi-man

Reputation: 4686

Answer mostly take from here but adapted for the @ionic-native/camera plugin getPicture command.

private urltoFile(url, filename, mimeType) {
    return (fetch(url)
        .then(function(res){return res.arrayBuffer();})
        .then(function(buf){return new File([buf], filename, {type:mimeType});})
    );
}

getPicture() {
    const options: CameraOptions = {
      quality: 50,
      destinationType: this.camera.DestinationType.DATA_URL,
      encodingType: this.camera.EncodingType.JPEG,
      mediaType: this.camera.MediaType.PICTURE,
      correctOrientation: true
    }

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

      let base64Image = 'data:image/jpeg;base64,' + imageData
      this.urltoFile(base64Image, 'filename.jpg', 'image/jpeg')
      .then((file) => {
          // You now have a file object that you can attach to a form e.g.
          this.myForm.get("imageToUpload").setValue(file)        
      })

    }, (err) => {
     // Handle error
    });
}

Key points to note are

  1. Destination type must be DATA_URL
  2. Must prepend data:image/jpeg;base64, to the imageData

Upvotes: -1

Related Questions